我有简单的一行功能:
revRange :: (Char,Char) -> [Char]
revRange t = unfoldr (\b -> if b == (pred (fst t)) then Nothing else Just (b, pred b)) (snd t)
效果很好:
*Main Data.List> revRange ('a', 'f')
"fedcba"
然后我想将unfoldr 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)
现在,我有一个奇怪的错误:
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
答案 0 :(得分:7)
首先,格式化代码:
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)
接下来,使用Hoogle仔细检查unfoldr
的类型:
unfoldr :: (b -> Maybe (a, b)) -> b -> [a]
接下来,将类型签名添加到fun
,以便GHC告诉您问题所在。根据{{1}}的类型,unfoldr
应具有以下类型:
fun
,因为原始示例中b ~ Char
a ~ Char
fun :: Char -> Maybe (Char, Char)
为unfoldr
。
我通常喜欢验证小块,因此我们可以删除snd t
的定义,只使用类型签名:
foo
GHC抱怨revRange :: (Char,Char) -> [Char]
revRange t = unfoldr fun t
fun:: Char -> Maybe (Char, Char)
fun b = error ""
类型为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 ""
的定义。我们可以删除lambda并将fun
作为b
的正常参数:
fun
我们立即看到另一个明显的问题:fun:: Char -> Maybe (Char, Char)
fun t b = if b == (pred (fst t))
then Nothing
else Just (b, pred b)
需要两个参数,但签名说它只需要一个!
由于fun
是原始lambda中的常量,我们可以通过在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)
使用与上述相同的方法,在revRange :: (Char,Char) -> [Char]
revRange = unfoldr fun2
的签名中,我们需要unfoldr
和b ~ (Char,Char)
。所以我们希望a ~ Char
具有类型
fun2
我会将fun2 :: ((Char,Char) -> Maybe (Char, (Char, Char)))
的定义作为练习。作为提示,我建议采用惯例,该对的第一部分是常量并保持fun2
。