如何解决Haskell中的字符串组合
我正在用Haskell编写一种算法,以简化上下文无关的语法,而且我一直在努力消除null产生式,更具体地说,是用其他产生物中的nullable非终结符的“替代”。
给出一个字符串,比方说“ ASA”,我想返回一个通过删除每次出现的字符“ A”一,二,...而构建的字符串列表。
明确地说,鉴于“ ASA”,我想返回以下代码:["SA","AS","S"]
。
在Python中,我做起来很容易,但是在Haskell中,我不知道如何遍历字符串并按我的意愿操纵它。可能是因为我仍然不习惯使用函数式编程。
解决方法
基于库的方法:
给定的输入字符可能会或可能不会出现在任何输出部分字符串中。因此,让Haskell Maybe
type transformer参与进来似乎很自然。它类似于C ++中的std::optional。
我们可以拥有一个expand
函数,该函数将与每个输入字符相关联的对应可能性的列表:
$ ghci
λ>
λ> st = "ASA"
λ>
λ> expand ch = if (ch == 'A') then [ Just ch,Nothing ] else [ Just ch ]
λ>
λ> map expand st
[[Just 'A',Nothing],[Just 'S'],[Just 'A',Nothing]]
λ>
基本上,我们需要的是上述列出的可能性的笛卡尔积。列表笛卡尔积可以通过使用高度多态的sequence库函数来获得:
λ>
λ> sequence (map expand st)
[[Just 'A',Just 'S',Just 'A'],[Nothing,Nothing]]
λ>
接下来,我们需要将[Just 'A',Nothing]
更改为['A','S'],在Haskell中它与“ AS”完全相同。所需的功能将具有其类型签名:
func :: [Maybe α] -> [α]
如果我们将此候选类型签名提交到Hoogle,我们很容易获得库函数catMaybes:
λ>
λ> import qualified Data.Maybe as Mb
λ>
λ> Mb.catMaybes [Just 'A',Nothing]
"AS"
λ>
λ> map Mb.catMaybes (sequence (map expand st))
["ASA","AS","SA","S"]
λ>
,我们只需要从最后一个列表中删除完整的字符串“ ASA”即可。
当然,没有必要将其限制为Char
数据类型。具有适当的相等性测试的任何类型都可以。特权字符“ A”应设为可变参数。总体而言,这为我们提供了以下代码:
import qualified Data.Maybe as Mb
multiSuppressor :: Eq α => α -> [α] -> [[α]]
multiSuppressor e xs =
let expand e1 = if (e1 == e) then [ Just e1,Nothing ] else [ Just e1 ]
maybes = sequence (map expand xs)
res1 = map Mb.catMaybes maybes
in
-- final massaging as the whole list is normally unwanted:
if (null xs) then [[]] else filter (/= xs) res1
关于效率的说明:
函数sequence
是多态的。列表中的笛卡尔积不是生命中唯一的角色。不幸的是,这碰巧会带来不幸的副作用,即如果您超出玩具大小的示例,其内存消耗可能会变得非常大。
如果这成为问题,则可以改用以下基于an idea by K. A. Buhr的替换代码:
cartesianProduct :: [[α]] -> [[α]]
cartesianProduct xss =
map reverse (helper (reverse xss))
where
helper [] = [[]]
helper (ys:zss) = [y:zs | zs <- helper zss,y <- ys]
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。