所以我有以下代码:
module Queue where
class Queue t
where
enqueue :: t a -> a -> t a
dequeue :: t a -> Maybe (t a, a)
- 和:
module DataQueue where
import Queue
data DQueue a = Empty | Enqueue a (DQueue a)
deriving (Eq, Show, Read)
instance Queue DQueue
where
enqueue (Empty) s = Enqueue s (Empty)
enqueue (Enqueue v ss) s = Enqueue s (Enqueue v ss)
dequeue Empty = Nothing
dequeue (Enqueue a (ss)) = Just(ss)
我将一个元素添加到列表(入队),这很好。我还使用dequeue函数删除列表中的元素。不知何故,我的出队函数的最后一行出错了。它说:
“无法将预期类型
(DQueue a, a)
与实际类型DQueue a
”匹配
我真的不明白如何解决这个问题。
答案 0 :(得分:4)
查看dequeue的类型签名:
dequeue :: t a -> Maybe (t a, a)
...并将其与您在该行中实际返回的内容进行比较:
dequeue (Enqueue a (ss)) = Just(ss)
类型不匹配。你能解决它吗?
<强>操作实例强>
dequeue
的类型为t a -> Maybe (t a, a)
,这意味着它需要一个类型为t a
的参数,并且应返回Maybe (t a, a)
类型的值。
打破这种类型,我们从最外面的'事物'开始:Maybe
('事物'被称为类型构造函数)。因此,无论我们返回什么,都必须是Nothing
或Just <some value>
。
Just
中的内容是“Maybe
内部”,在这种情况下是(t a, a)
类型的值,它是t a
的元组(对)和{ {1}}。
现在看看你的代码说了什么:
a
返回值dequeue (Enqueue a (ss)) = Just(ss)
可以写为Just(ss)
。让我们确定Just ss
的类型。由于我们定义:
ss
因此data DQueue a = Empty | Enqueue a (DQueue a)
^^^^^^^^^^ <-- ss is of this type
的类型为ss
。因此DQueue a
的类型为:Just ss
。
现在,我们需要返回Maybe (DQueue a)
。在Maybe (t a, a)
类的实例中,Queue
为t
,因此要返回的类型更具体:DQueue
,但我们目前有Maybe (DQueue a, a)
(请记住Maybe (DQueue a)
为ss
,因此DQueue a
为Just ss
)。
所以要解决这个问题,我们应该返回Maybe (DQueue a)
而不是Just ss
。这一对取决于我们希望Just (some pair)
的行为方式。如果它像一个弹出最后排队结果的堆栈,它可以是dequeue
。否则,请参阅另一个讨论如何实现它的答案。
答案 1 :(得分:4)
根据您的Queue
类,您的dequeue
函数必须在删除元素后返回队列。它应该被定义为
dequeue Empty = Nothing
dequeue (Enqueue a Empty) = Just (Empty, a)
dequeue (Enqueue a (ss)) = do
(next, v) <- dequeue ss
return (Enqueue a next, v)
这个定义假设你在列表的开头排队,并从最后出列。
第三个dequeue
匹配是递归调用dequeue
走到列表的末尾,在那里它获取列表值(请参阅第二个dequeue
匹配),然后构建使用除最后一个元素以外的所有元素再次使用Enqueue列表。
上面的示例利用了Maybe
monad和do
语法。它可以表示如下,如果这更有意义:
dequeue (Enqueue a ss) =
case dequeue ss of
Just (next, v) -> Just (Enqueue a next, v)
Nothing -> Nothing