haskell 无法将类型“[t0 ->t]”->Bool与Bool匹配

8xiog9wr  于 2022-11-30  发布在  其他
关注(0)|答案(2)|浏览(180)

我是一个初学者在Haskell。我面临的错误是在标题。下面是我的Haskell代码。

member atm lizt = if null lizt
                     then False
                     else if atm == head lizt then True else member(atm (tail lizt))
                     
main = print(member 1 [2, 1])

错误消息

GHCi, version 8.10.6: https://www.haskell.org/ghc/  :? for help
Loaded GHCi configuration from /home/runner/member/.ghci
[1 of 1] Compiling Main             ( Main.hs, interpreted )

Main.hs:1:1: error:
    • Couldn't match type ‘[t0 -> t] -> Bool’ with ‘Bool’
      Expected type: t -> Bool
        Actual type: (t0 -> t) -> [t0 -> t] -> Bool
    • Relevant bindings include
        member :: t -> Bool (bound at Main.hs:1:1)
  |
1 | member atm lizt = if null lizt
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...

Main.hs:5:14: error:
    • Couldn't match expected type ‘[a1] -> a0’ with actual type ‘Bool’
    • The function ‘member’ is applied to two arguments,
      but its type ‘t1 -> Bool’ has only one
      In the first argument of ‘print’, namely ‘(member 1 [2, 1])’
      In the expression: print (member 1 [2, 1])
  |
5 | main = print(member 1 [2, 1])
  |              ^^^^^^^^^^^^^^^
Failed, no modules loaded.
 
<interactive>:1:1: error:
    • Variable not in scope: main
    • Perhaps you meant ‘min’ (imported from Prelude)
 ^C Leaving GHCi.
repl process died unexpectedly: 
GHCi, version 8.10.6: https://www.haskell.org/ghc/  :? for help
Loaded GHCi configuration from /home/runner/member/.ghci

如果给定的整数(在我的例子中是atm)出现在给定的列表中,我试图打印true,否则打印false。在我添加递归调用之前,代码正在工作(只是检查列表的第一个元素)。

hsgswve4

hsgswve41#

我认为您对函数的调用有误解。
member是一个两个参数的函数。它可以像member atm (tail lizt)一样调用。当你像member(atm (tail lizt))一样调用它时,atm (tail lizt)会告诉它把atm作为tail lizt上的一个函数来调用。但是atm不应该是一个函数。你需要用两个参数atmtail lizt来调用member
你得到的编译器错误并不是很严重。编译器知道有什么地方出错了,但它并不确切地知道是什么。这类令人困惑的错误在Haskell中经常发生。处理它们的最好方法是注意到你有一个类型错误,然后开始添加类型签名。如果你在代码中添加你想要的member的类型签名:

member :: Eq a => a -> [a] -> Bool

这样编译器就能更好地了解您要执行的操作,并给出更有帮助的答案:

• Couldn't match expected type ‘Bool’
                  with actual type ‘[a0] -> Bool’
    • Probable cause: ‘member’ is applied to too few arguments
      In the expression: member (atm (tail lizt))
      In the expression:
        if atm == head lizt then True else member (atm (tail lizt))
      In the expression:
        if null lizt then
            False
        else
            if atm == head lizt then True else member (atm (tail lizt))
  |
4 |                      else if atm == head lizt then True else member(atm (tail lizt))
  |                                                              ^^^^^^^^^^^^

如果您只是在开始时添加类型签名,这也会有所帮助,因为它们有助于将您的代码应该做的事情传达给其他人。

vfhzx4xs

vfhzx4xs2#

除了已经提供的answer之外,我想指出的是,模式匹配和条件保护可以显著地清理代码。
head的使用将lizt标识为列表,因此我们可以对其进行模式匹配,而不是使用nullheadtail;然后使用条件保护来确定第一个元素是否等于我们要查找的值。

member _ [] = False
member atm (hd:tl) 
  | atm == hd = True
  | otherwise = member atm tl

当然,这基本上只是elem
除了上述情况,至少要格式化代码以减少水平滚动。

member atm lizt = 
  if null lizt then False
  else if atm == head lizt then True 
  else member atm (tail lizt)

相关问题