奇怪的无法匹配类型错误
Weird couldn't match type error
我有简单的一行函数:
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
首先,格式化您的代码:
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 就会告诉您问题出在哪里。根据unfoldr
的类型,fun
的类型应该是:
b ~ Char
a ~ Char
fun :: Char -> Maybe (Char, Char)
因为在原始示例中您是 unfoldr
snd t
。
平时喜欢验证小块,所以我们可以去掉foo
的定义,直接使用类型签名:
revRange :: (Char,Char) -> [Char]
revRange t = unfoldr fun t
fun:: Char -> Maybe (Char, Char)
fun b = error ""
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 ""
接下来,再次添加fun
的定义。我们可以删除 lambda 并将 b
作为 fun
:
的普通参数
fun:: Char -> Maybe (Char, Char)
fun t b = if b == (pred (fst t))
then Nothing
else Just (b, pred b)
我们立即看到另一个明显的问题:fun
接受 两个 个参数,但签名说它应该只接受一个!
由于t
在原来的lambda中是一个常量,我们可以通过在revRange
中部分应用fun
来解决这个问题,所以最终答案是:
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
的定义留作练习。作为提示,我建议采用该对的第一部分是常量并保持 fst t
.
的约定
我有简单的一行函数:
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
首先,格式化您的代码:
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 就会告诉您问题出在哪里。根据unfoldr
的类型,fun
的类型应该是:
b ~ Char
a ~ Char
fun :: Char -> Maybe (Char, Char)
因为在原始示例中您是 unfoldr
snd t
。
平时喜欢验证小块,所以我们可以去掉foo
的定义,直接使用类型签名:
revRange :: (Char,Char) -> [Char]
revRange t = unfoldr fun t
fun:: Char -> Maybe (Char, Char)
fun b = error ""
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 ""
接下来,再次添加fun
的定义。我们可以删除 lambda 并将 b
作为 fun
:
fun:: Char -> Maybe (Char, Char)
fun t b = if b == (pred (fst t))
then Nothing
else Just (b, pred b)
我们立即看到另一个明显的问题:fun
接受 两个 个参数,但签名说它应该只接受一个!
由于t
在原来的lambda中是一个常量,我们可以通过在revRange
中部分应用fun
来解决这个问题,所以最终答案是:
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
的定义留作练习。作为提示,我建议采用该对的第一部分是常量并保持 fst t
.