【问题标题】:Haskell - Non-exhaustive patterns in function using data type [closed]Haskell - 使用数据类型的函数中的非详尽模式[关闭]
【发布时间】:2019-04-04 03:33:51
【问题描述】:

我试图在 Haskell wiki 上解决这个问题:https://wiki.haskell.org/99_questions/11_to_20(问题 12)

我的解决方法如下:

data Repeats a = Single a | Multiple Int a deriving Show

encodelens :: Eq a => [a] -> [Repeats a]
encodelens xs = foldr (\x acc -> case acc of
                                  [] -> [Single x]
                                  (l:ls) -> case l of
                                             (Single x') -> if x == x'
                                                             then [(Multiple 2 x)] ++ ls
                                                             else [(Single x)] ++ (l:ls)
                                             (Multiple c x') -> if x == x'
                                                                 then [(Multiple (c+1) x)] ++ ls
                                                                 else [(Single x)] ++ (l:ls)
                      ) [] xs

decodelens :: Eq a => [Repeats a] -> [a]
decodelens [] = []
deocdelens (r:rs) = case r of
                     (Single x) -> [x] ++ decodelens rs
                     (Multiple c x) -> take c (repeat x) ++ decodelens rs

decodelens 不起作用,它失败了:

decodelens [Multiple 4 'a',Multiple 2 'b',Multiple 2 'c',Multiple 2 'd',Single 'e',Multiple 3 'f']

"*** Exception: encode-len-with-cardinality.hs:(17,1)-(19,47): Non-exhaustive patterns in function decodelens

我不确定它是如何无法进行模式匹配的。

更新

正如下面 cmets 所指出的,错误在于第二个模式匹配 deocdelens 的函数名。 不知道有没有办法避免这样的错误?

【问题讨论】:

  • 看函数名的拼写:deocde vs. decode。
  • 该死,这么简单的错误。有没有办法避免这样的错误?
  • 我们都会犯这样的错误,这就是为什么 ghc 是一个很棒的结对编程合作伙伴。
  • @Ngm 是的,有一种方法——使用-Wall 开启警告! GHC 应该警告您 1) 非详尽匹配和 2) 函数 deocde 开始定义时没有类型注释 deocde :: ...。第二个应该指出问题。

标签: haskell recursion types


【解决方案1】:

这确实是一种难以捕捉的错误。请注意,如果您在 decodelens 的签名或第一个模式上有拼写错误,GHC 会抱怨,因为签名必须与函数定义“相邻”。

我认为您可以在这里做的最好的事情是打开-Wmissing-signatures。对于上面的代码,这将触发关于顶级函数deocdelens 没有签名的警告。当然,这意味着您必须为所有顶级函数显式编写签名,但通常还是鼓励这样做。

【讨论】:

    【解决方案2】:

    无论 Haskell 与其他语言如何,防止此类问题发生的一件事是养成从不输入三个字母以上的名称的习惯(第一次编写时除外,通常用于签名)。这就是自动完成功能的用途。

    当然,这有其自身的问题——我不止一次发现自己在第一次时输入了错误的名称,然后在我的程序中自动完成——“粘贴”它。这样就可以正常工作了,只是在阅读代码时有点尴尬...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多