List 使用列表和zip的Haskell函数的输出不正确
我的代码应该是一个字符串,例如,List 使用列表和zip的Haskell函数的输出不正确,list,haskell,List,Haskell,我的代码应该是一个字符串,例如,cccccchhrre并返回对的列表[('c',5),('h',2),('r',3),('e',1)]。该对的第一部分是字母,第二部分是在出现下一个字符串之前重复的次数 但是,当前我的代码返回[('c',11)]-这是字符串中的第一个字符和总字符数的长度: > fun4 "ccccchhrrre" [('c',11)] 我的问题是fun4。运行func3时 我非常感谢您的帮助,包括详细的解释。这里有几个问题。第一个是,当你写作时: func4 :: Str
cccccchhrre
并返回对的列表[('c',5),('h',2),('r',3),('e',1)]
。该对的第一部分是字母,第二部分是在出现下一个字符串之前重复的次数
但是,当前我的代码返回[('c',11)]
-这是字符串中的第一个字符和总字符数的长度:
> fun4 "ccccchhrrre"
[('c',11)]
我的问题是fun4
。运行func3时
我非常感谢您的帮助,包括详细的解释。这里有几个问题。第一个是,当你写作时:
func4 :: String -> [(Char, Int)]
func4 fun3 = zip (fun3)[length fun3]
此定义中的fun3
与您先前定义的fun3
函数没有任何关系。如果您打开编译器警告(例如,使用标志-Wall
),它将警告您在func4
的此定义中fun3
的绑定“隐藏”了现有绑定。这意味着它的处理方式与使用完整的单独名称相同:
func4 :: String -> [(Char, Int)]
func4 bob = zip (bob) [length bob]
因此,当您进行评估时:
func4 "ccccchhrrre"
根本不使用函数fun3
。相反,它被func4
的定义扩展为:
func4 "ccccchhrrre"
= zip "ccccchhrrre" [length "ccccchhrrre"]
= zip "ccccchhrrre" [11]
由于Haskell中的字符串是字符列表,这与:
= zip ['c','c',...] [11]
当您压缩两个列表,其中一个比另一个短时,压缩会在列表用完时结束,因此会产生:
= [('c', 11)]
并忽略字符列表的第二个和后面的元素
您可能想要的是编写func4
以获取字符串参数并将其传递给fun3
:
func4 :: String -> [(Char, Int)]
func4 xs = zip (fun3 xs) [length (fun3 xs)]
func4 :: [String] -> [(Char, Int)]
func4 [] = []
func4 (str : strs) = ??? : func4 strs
不幸的是,这不会进行类型检查。问题在于,这相当于:
func4 "ccccchhrrre"
= zip ["ccccc","hh","rrr","e"] [length ["ccccc","hh","rrr","e"]]
= zip ["ccccc","hh","rrr","e"] [4]
= [("ccccc", 4)]
它的类型是[(String,Char)]
,而不是您期望的[(Char,Char)]
如果你了解了<代码> MAP>代码>,你可能会认为知道:
是有用的。> map head ["ccccc","hh","rrr","e"]
"chre"
>
而“chre”
相当于列表['c','h','r','e']
。如果你能以某种方式得到一个长度的列表,就像你得到一个头部列表一样,这些列表将非常有用
如果您不想使用map
,您可能会发现编写一个func4
来处理fun3
的输出很有帮助,如下所示:
> func4 ["ccccc","hh","rrr","e"]
[('c',5),('h',2),('r',3),('e',1)]
>
它的签名稍有不同,但结构与您的fun3
:
func4 :: String -> [(Char, Int)]
func4 xs = zip (fun3 xs) [length (fun3 xs)]
func4 :: [String] -> [(Char, Int)]
func4 [] = []
func4 (str : strs) = ??? : func4 strs
然后,您的最终函数可以将fun3
和fun4
链接在一起:
rle :: String -> [(Char, Int)]
rle str = func4 (fun3 str)
对代码中的问题提供了很好的解释。这里有一个稍微不同的解决方案,我觉得更容易理解
fun3
可以用现有函数替换<代码>组获取一个列表并生成一个列表列表,其中包含相等的相邻元素:
> Data.List.group "ccccchhrrre"
["ccccc","hh","rrr","e"]
fun4
应该执行的工作也可以通过使用map
来简化。匿名函数\x->(头x,长度x)
接受一个参数x
,并生成一个元组,其第一个元素是x的头,第二个元素是x的长度。将此函数映射到组
的输出上,可以得到所需的结果:
> map (\x -> (head x, length x)) ["ccccc","hh","rrr","e"]
[('c',5),('h',2),('r',3),('e',1)]
现在,我们可以将组
和我们的映射
组合成一个函数,并给它一个更合适的名称:
-- Count adjacent repeated characters
countRep :: String -> [(Char, Int)]
countRep str = map (\x -> (head x, length x)) (List.group str)
只是为了好玩
我们编写的函数可以用于任何项目可以进行平等比较的列表!这里是无点样式:
countRep :: Eq a => [a] -> [(a, Int)]
countRep = map (liftA2 (,) head length) . List.group
什么是
fun2
?