在 Haskell CIS194 第 2 周练习 2 中使用匿名函数

Using anonymous functions in Haskell CIS194 Week 2 Exercise 2

我正在尝试通过 "CIS 194: Introduction to Haskell 2013" 课程学习 haskell,并且 运行 在第二周的练习 2 中遇到困难。我正在尝试使用辅助递归函数定义我的构建函数

reduce :: (a -> b -> b) -> [a] -> b -> b
reduce _ [] x = x
reduce f (x:xs) y  = reduce f xs (f x y)

这个函数的目标是递归地将列表[a]上的一个函数应用到b。这是因为我想递归地将 LogMessage 列表插入 MessageTree

build :: [LogMessage] -> MessageTree
build [] = Node Leaf (Unknown "") Leaf
build messages =
    reduce (\x y -> (insert x y)) tail(messages) (Node Leaf head(messages) Leaf)

但是当我尝试编译它时,我收到了一长串编译错误:

LogAnalysis.hs:42:22:
    Couldn't match expected type `t0 -> MessageTree'
                with actual type `MessageTree'
    In the return type of a call of `insert'
    Probable cause: `insert' is applied to too many arguments
    In the expression: (insert x y)
    In the first argument of `reduce', namely `(\ x y -> (insert x y))'

LogAnalysis.hs:42:31:
    Couldn't match expected type `MessageTree'
                with actual type `t0 -> MessageTree'
    In the second argument of `insert', namely `y'
    In the expression: (insert x y)
    In the first argument of `reduce', namely `(\ x y -> (insert x y))'

LogAnalysis.hs:42:35:
    Couldn't match expected type `[LogMessage]'
                with actual type `[a0] -> [a0]'
    In the second argument of `reduce', namely `tail'
    In the expression:
      reduce
        (\ x y -> (insert x y))
        tail
        (messages)
        (Node Leaf head (messages) Leaf)
    In an equation for `build':
        build messages
          = reduce
              (\ x y -> (insert x y))
              tail
              (messages)
              (Node Leaf head (messages) Leaf)

LogAnalysis.hs:42:40:
    Couldn't match expected type `t0 -> MessageTree'
                with actual type `[LogMessage]'
    In the third argument of `reduce', namely `(messages)'
    In the expression:
      reduce
        (\ x y -> (insert x y))
        tail
        (messages)
        (Node Leaf head (messages) Leaf)
    In an equation for `build':
        build messages
          = reduce
              (\ x y -> (insert x y))
              tail
              (messages)
              (Node Leaf head (messages) Leaf)

LogAnalysis.hs:42:51:
    Couldn't match expected type `MessageTree -> t0'
                with actual type `MessageTree'
    The function `Node' is applied to four arguments,
    but its type `MessageTree
              -> LogMessage -> MessageTree -> MessageTree'
    has only three
    In the fourth argument of `reduce', namely
      `(Node Leaf head (messages) Leaf)'
    In the expression:
      reduce
        (\ x y -> (insert x y))
        tail
        (messages)
        (Node Leaf head (messages) Leaf)

LogAnalysis.hs:42:61:
    Couldn't match expected type `LogMessage'
            with actual type `[a1] -> a1'
    In the second argument of `Node', namely `head'
    In the fourth argument of `reduce', namely
      `(Node Leaf head (messages) Leaf)'
    In the expression:
      reduce
        (\ x y -> (insert x y))
        tail
        (messages)
        (Node Leaf head (messages) Leaf)

LogAnalysis.hs:42:66:
    Couldn't match expected type `MessageTree'
            with actual type `[LogMessage]'
    In the third argument of `Node', namely `(messages)'
    In the fourth argument of `reduce', namely
      `(Node Leaf head (messages) Leaf)'
    In the expression:
      reduce
        (\ x y -> (insert x y))
        tail
        (messages)
        (Node Leaf head (messages) Leaf)
Failed, modules loaded: Log.

供参考,这是我的插入函数,它编译正确

insert :: LogMessage -> MessageTree -> MessageTree
insert (Unknown _) tree = tree
insert _ tree@(Node _ (Unknown _) _) = tree
insert message Leaf = Node Leaf message Leaf
insert message@(LogMessage _ timeStampMessage _) (Node left m@(LogMessage _ timeStampTree _) right)
    | timeStampMessage < timeStampTree  = Node (insert message left) m right
    | timeStampMessage > timeStampTree  = Node left m (insert message right)
    | timeStampMessage == timeStampTree = Node left message right

括号不表示函数调用;它们只会影响运算符的优先级。函数应用用并列表示(可以认为是最高优先级的运算符)。

这一行

build messages = reduce (\x y -> (insert x y)) tail(messages) (Node Leaf head(messages) Leaf)

应首先缩短为

build messages = reduce insert tail(messages) (Node Leaf head(messages) Leaf)

这样可以更容易地看到括号的正确方法:

build messages = reduce insert (tail messages) (Node Leaf (head messages) Leaf)

但是,使用模式匹配比使用 headtail 更好:

build (x:xs) = reduce insert xs (Node Leaf x Leaf)