Dav*_*vid 1 haskell types fold unfold
我有简单的一行功能:
revRange :: (Char,Char) -> [Char]
revRange t = unfoldr (\b -> if b == (pred (fst t)) then Nothing else Just (b, pred b)) (snd t)
Run Code Online (Sandbox Code Playgroud)
效果很好:
*Main Data.List> revRange ('a', 'f')
"fedcba"
Run Code Online (Sandbox Code Playgroud)
然后我想提取展开lambda作为唯一函数:
revRange :: (Char,Char) -> [Char]
revRange t = unfoldr fun t
fun t = (\b -> if b == (pred (fst t)) then Nothing else Just (b, pred b)) (snd t)
Run Code Online (Sandbox Code Playgroud)
现在,我有一个奇怪的错误:
Couldn't match type `Char' with `(Char, Char)'
Expected type: (Char, Char) -> Maybe (Char, (Char, Char))
Actual type: (Char, Char) -> Maybe (Char, Char)
In the first argument of `unfoldr', namely `fun'
In the expression: unfoldr fun t
Run Code Online (Sandbox Code Playgroud)
首先,格式化代码:
revRange :: (Char,Char) -> [Char]
revRange t = unfoldr fun t
fun t = (\b -> if b == (pred (fst t))
then Nothing
else Just (b, pred b)) (snd t)
Run Code Online (Sandbox Code Playgroud)
接下来,仔细检查unfoldr使用Hoogle的类型:
unfoldr :: (b -> Maybe (a, b)) -> b -> [a]
Run Code Online (Sandbox Code Playgroud)
接下来,添加一个类型签名,fun以便GHC告诉您问题所在.根据类型unfoldr,fun应该有类型:
b ~ Char
a ~ Char
fun :: Char -> Maybe (Char, Char)
Run Code Online (Sandbox Code Playgroud)
因为你是unfoldr在原始的例子中snd t.
我通常喜欢验证小块,所以我们可以删除定义foo并只使用类型签名:
revRange :: (Char,Char) -> [Char]
revRange t = unfoldr fun t
fun:: Char -> Maybe (Char, Char)
fun b = error ""
Run Code Online (Sandbox Code Playgroud)
GHC抱怨t类型(Char, Char)但fun期望类型Char.你打电话unfoldr fun t而不是unfoldr fun (snd t)原来的例子.将该位移fun入revRange:
revRange :: (Char,Char) -> [Char]
revRange t = unfoldr fun (snd t)
fun:: Char -> Maybe (Char, Char)
fun b = error ""
Run Code Online (Sandbox Code Playgroud)
接下来,fun再次添加定义.我们可以删除lambda并将其b作为正常参数放入fun:
fun:: Char -> Maybe (Char, Char)
fun t b = if b == (pred (fst t))
then Nothing
else Just (b, pred b)
Run Code Online (Sandbox Code Playgroud)
我们立即看到另一个明显的问题:fun拿两个参数,但签名说它应该只拿一个!
由于t是在原拉姆达恒定,就可以解决这个问题,通过部分应用fun中revRange,所以最后的答案是:
revRange :: (Char,Char) -> [Char]
revRange t = unfoldr (fun t) (snd t)
fun:: (Char, Char) -> Char -> Maybe (Char, Char)
fun t b = if b == (pred (fst t))
then Nothing
else Just (b, pred b)
Run Code Online (Sandbox Code Playgroud)
为了解决你的评论,你想写
revRange :: (Char,Char) -> [Char]
revRange = unfoldr fun2
Run Code Online (Sandbox Code Playgroud)
使用与上述相同的方法,在unfoldr我们需要的签名b ~ (Char,Char)和a ~ Char.所以我们想要fun2这种类型
fun2 :: ((Char,Char) -> Maybe (Char, (Char, Char)))
Run Code Online (Sandbox Code Playgroud)
我将把这个定义fun2留作练习.作为提示,我建议采用惯例,即该对的第一部分是常数并保持不变fst t.