haskell中列表的出列函数

时间:2016-06-15 12:37:21

标签: haskell queue

所以我有以下代码:

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”匹配

我真的不明白如何解决这个问题。

2 个答案:

答案 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('事物'被称为类型构造函数)。因此,无论我们返回什么,都必须是NothingJust <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)类的实例中,Queuet,因此要返回的类型更具体:DQueue,但我们目前有Maybe (DQueue a, a)(请记住Maybe (DQueue a)ss,因此DQueue aJust 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