我做了一个名为Queue的自定义数据类型,并尝试将“整数”排列在“列表”的末尾。
data Queue = Ele Int Queue | Nil
-- [..] some other Functions
enqueue :: Int -> Queue -> Queue
enqueue x Nil = (Ele x Nil)
enqueue x (Ele _ restEles) = reverse (Ele x reverse restEles)
我收到错误:
“无法匹配预期类型
Queue' with actual type
[a0]'”。
我认为是,因为该函数不知道如何处理我的数据类型。我在这儿吗?我怎样才能解决这个问题?我是否必须编写自己的反向功能?如果你能帮助我,因为我还在学习Haskell并且不理解这一点:
reverse = foldl (flip (:)) []
答案 0 :(得分:5)
是的,您已定义了一种新的数据类型。尽管它在结构上与列表类似,但Haskell会将其视为完全不同的。因此,您必须确实定义一个新的reverse
函数,或者定义一个函数,将您的类型转换为标准列表并返回。
但对于enqueue
,您不一定需要reverse
。在enqueue
的情况下,您可以在restEles
上递归调用Ele
,并将第一个元素放回到结果的前面。
这里是您完成直接递归定义的模式:
enqueue :: Int -> Queue -> Queue
enqueue x Nil = Ele x Nil
enqueue x (Ele firstEle restEles) = ...
对于......,你必须按照我上面所说的做法:以递归方式调用enqueue
元素并将第一个元素放回顶部。
答案 1 :(得分:2)
反向的类型是:
reverse :: [a] -> [a]
队列不是 [a] 。您需要实现自己的 reverseQueue 功能,该功能可以理解您的数据类型。
答案 2 :(得分:1)
至于问题的第二部分:
reverse :: [a] -> [a]
reverse = foldl (flip (:)) []
首先,确保您了解foldl
。它是一个强大的高阶函数,这意味着它可以用来实现许多其他函数(sum
,map
,filter
,当然还有reverse
)。你可以阅读它here。
现在,我们来看一个更简单的版本:
reverse :: [a] -> [a]
reverse xs = foldl (\ys y -> y:ys) [] xs
\ys y -> y:ys
是一个非常简单的函数:它采用列表(ys
)和值(y
)并在列表(y:ys
)之前插入值。所以我们的计划是:从空列表([]
)开始,将xs
中的第一项插入其左侧,取结果并将第二项插入其左侧,依此类推。
让我们用一个简单的列表来模拟它 - [1,2,3]
:
我们从空列表开始 - []
将第一项(1
)添加到左侧:[1]
将第二项(2
)添加到[1]
左侧:[2,1]
将第三项(3
)添加到[2,1]
左侧:[3,2,1]
我们已成功撤销[1,2,3]
。
现在,flip
是一个函数,它接受一个函数并“翻转”它的参数。因此,如果subtract a b
为a-b
,则(flip subtract) a b
等于subtract b a
- b-a
。因此,如果(:)
是一个带有项y
和列表ys
并将该项添加到列表开头的函数,则flip (:)
与翻转的功能相同参数 - 它需要一个列表和一个项目,就像我们的函数一样 - \ys y -> y:ys
。所以我们可以替换它们中的两个:
reverse :: [a] -> [a]
reverse xs = foldl (flip (:)) [] xs
现在我们用pointfree样式编写并从等式的两边消除xs
并得到最终版本:
reverse :: [a] -> [a]
reverse = foldl (flip (:)) []