第一个问题:
定义一个使用分隔符值将列表列表连接在一起的函数
类型定义应该是这样的:
intersperse :: a -> [[a]] -> [a]
分隔符应出现在列表的元素之间,但不应该跟在最后一个元素之后 您的函数应该表现如下:
ghci> :load Intersperse
[1 of 1] Compiling Main ( Intersperse.hs, interpreted )
Ok, modules loaded: Main.
ghci> intersperse ',' []
""
ghci> intersperse ',' ["foo"]
"foo"
ghci> intersperse ',' ["foo","bar","baz","quux"]
"foo,bar,baz,quux"
一段时间后我设法解决它:
intersperse myChar lists
| lists == [] = ""
| otherwise = attach myChar lists
where attach myChar (x:[]) = x
attach myChar (x:xs) = x ++ (myChar : []) ++ attach myChar xs
但是,正如您所见,它没有类型定义 如果我将类型定义放在函数上方,我会收到错误。 为什么呢?
第二个问题:
在我得到这个解决方案之前,我想把另一名警卫放在警卫名单中。
这个quard应该是在第一个后卫之后。
我想检查列表变量中是否只有一个列表,所以我只返回列表变量。
但我不能做那样的警卫(再一次,错误就是生命: - )):
| lists == (x:[]) = lists
这也不起作用:
| lists == (_:[]) = lists
为什么为什么? :-)。 在此之后,我试图让其他警卫:
| length lists == 1 = lists
但它也引发了一个错误。
(顺便说一句,我不需要那些警卫,因为我发现“where”关键字之后的第一个模式,正是我想要的。
这就是我所说的模式:
附上myChar(x:[])= x
但是,我仍然想知道为什么我试过的调子,不起作用。 另外,我找到了这个解决方案,运气好,我不认为每次我会注意到这样的事情:-)
非常感谢: - )。
P.S。 本练习来自书籍real world haskell。
答案 0 :(得分:3)
""
的类型为[Char]
,但您的类型签名称intersperse
会返回[a]
,其中a
取决于输入类型,所以类型不匹配。
我认为你不能在守卫内部进行模式匹配。
对于这个警卫
| length lists == 1 = lists
lists
的类型为[[a]]
,但您应该返回[a]
。也就是说,如果lists
为["foo"]
,则您希望返回"foo"
。您不想返回["foo"]
。
答案 1 :(得分:2)
问题是你的函数不是通用的,它只适用于字符串(Char列表)。如果您将第二行更改为
lists == [] = []
你会得到你想要的东西,尽管由于equals运算符而依赖于Eq
类型类。它甚至可以用于字符串,因为所有字符串都是列表,但并非所有列表都是字符串。
顺便说一句,您可以通过使用模式匹配来进一步概括您的功能:
intersperse myChar lists = case lists of
[] -> []
lists -> attach myChar lists
where attach myChar (x:[]) = x
attach myChar (x:xs) = x ++ (myChar : []) ++ attach myChar xs
或者,更具惯用性:
intersperse _ [] = []
intersperse x xs = attach x xs
where attach myChar (x:[]) = x
attach myChar (x:xs) = x ++ (myChar : []) ++ attach myChar xs
摆脱内在功能:
intersperse _ [] = []
intersperse _ (xs:[]) = xs
intersperse x (xs:xss) = (xs ++ x:intersperse x xss)
关于第二个问题,你在守卫中使用的等于运算符需要双方的值。你不能模仿匹配它。也许你正在寻找的东西就像这里的第二个改进。
答案 2 :(得分:1)
这会引起错误。
为什么?
除了你用case of
写它之外,它和你一样。
intersperse :: a -> [[a]] -> [a]
intersperse myChar lists
| lists == [] = []
| otherwise = attach myChar lists
where attach myChar (x:[]) = x
attach myChar (x:xs) = x ++ (myChar : []) ++ attach myChar xs
这不会引发错误(这是你所分割的):
intersperse :: a -> [[a]] -> [a]
intersperse myChar lists = case lists of
[] -> []
lists -> attach myChar lists
where attach myChar (x:[]) = x
attach myChar (x:xs) = x ++ (myChar : []) ++ attach myChar xs
但是在我的例子中(这里的第一个功能),我将守卫改为你建议的,但我仍然得到一个错误。
为什么会这样?
非常感谢。
答案 3 :(得分:0)
这可能是错误的,但它似乎可行
intersperse :: a -> [[a]] -> [a]
intersperse _ [] = []
intersperse separator [xs] = xs
intersperse separator (x:xs) = x ++ [separator] ++ (intersperse separator xs)