代码之家  ›  专栏  ›  技术社区  ›  David

怪异无法匹配类型错误

  •  1
  • David  · 技术社区  · 9 年前

    我有一个简单的单行函数:

    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
    
    1 回复  |  直到 9 年前
        1
  •  7
  •   crockeea    9 年前

    首先,格式化代码:

    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)
    

    接下来,再次检查 unfoldr 使用 Hoogle :

    unfoldr :: (b -> Maybe (a, b)) -> b -> [a]
    

    接下来,将类型签名添加到 fun 这样GHC会告诉你问题是什么 打开文件夹 , 享乐 应具有以下类型:

    b ~ Char
    a ~ Char
    
    fun :: Char -> Maybe (Char, Char)
    

    既然你是 打开文件夹 在原始示例中 snd t .

    我通常喜欢验证小块,因此我们可以删除 foo 只需使用类型签名:

    revRange :: (Char,Char) -> [Char]
    revRange t = unfoldr fun t
    
    fun:: Char -> Maybe (Char, Char)
    fun b = error ""
    

    GHC抱怨说 t 具有类型 (Char, Char) 但是 享乐 应为类型 Char 。您已致电 unfoldr fun t 而不是 unfoldr fun (snd t) 如在原始示例中那样。从 享乐 进入 revRange :

    revRange :: (Char,Char) -> [Char]
    revRange t = unfoldr fun (snd t)
    
    fun:: Char -> Maybe (Char, Char)
    fun b = error ""
    

    接下来,添加 享乐 再一次我们可以去掉lambda b 作为 享乐 :

    fun:: Char -> Maybe (Char, Char)
    fun t b = if b == (pred (fst t)) 
              then Nothing 
              else Just (b, pred b)
    

    我们立即看到另一个突出的问题: 享乐 参数,但签名表示只需要一个!

    自从 是原始lambda中的常量,我们可以通过部分应用 享乐 在里面 转速范围 ,因此最终答案是:

    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
    

    使用与上述相同的方法 打开文件夹 我们需要 b ~ (Char,Char) a ~ Char 。所以我们想 fun2 要有类型

    fun2 :: ((Char,Char) -> Maybe (Char, (Char, Char)))
    

    我会留下定义 功能2 作为练习。作为一个提示,我建议采用这样一种惯例,即这一对的第一部分是恒定的 fst t .

    推荐文章