Haskell没有得到我的函数依赖性
我试图创建一个实现基本队列行为的队列类型类。我的代码如下:Haskell没有得到我的函数依赖性,haskell,constraints,typeclass,functional-dependencies,Haskell,Constraints,Typeclass,Functional Dependencies,我试图创建一个实现基本队列行为的队列类型类。我的代码如下: {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE FunctionalDependencies #-} data QueueA a = QueueA { front :: [a], rear :: [a] } class Queue a b | a -> b where empty :: a null :: a -> Boo
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
data QueueA a = QueueA { front :: [a], rear :: [a] }
class Queue a b | a -> b where
empty :: a
null :: a -> Bool
head :: a -> Maybe b
tail :: a -> Maybe a
toList :: a -> [b]
(|>) :: a -> b -> a
instance Queue (QueueA a) where
empty = QueueA [] []
null (QueueA [] []) = True
null _ = False
head (QueueA [] []) = Nothing
head (QueueA (x:xs) _) = Just x
tail (QueueA [] []) = Nothing
tail (QueueA (x:xs) (y:ys)) = Just $ QueueA (xs ++ [y]) ys
toList (QueueA x y) = x ++ y
(|>) (QueueA x y) e = if (length x > length y) then QueueA (init $ e : x) ((last x) : y) else QueueA (e : x) y
不幸的是,当我试图编译代码时,ghc告诉我以下几点:
queue.hs:15:10: error:
• Expecting one more argument to ‘Queue (QueueA a)’
Expected a constraint,
but ‘Queue (QueueA a)’ has kind ‘* -> Constraint’
• In the instance declaration for ‘Queue (QueueA a)’
|
15 | instance Queue (QueueA a) where
| ^^^^^^^^^^^^^^^^
不过,我并没有真正明白这一点。我所知道的是,我的实例声明中队列的模式必须正确,因为它与我在上面的数据类型中指定的模式完全相同。我尝试了我的实例声明的几种变体,但都没有成功。我只是忽略了什么吗?如何使其可编译?实例需要与相应类相同数量的参数。但是,您创建了一个具有2个参数的类和一个仅具有1个参数的对应实例。要使其编译,可以执行
实例队列(QueueA a)where
而不是实例队列(QueueA a)where
。(您还需要FlexibleInstances
扩展。)该类不需要多个参数。相反,该类应该采用高阶类型作为其参数,而不是具体类型
class Queue t where
empty :: t a
null :: t a -> Bool
head :: t a -> Maybe a
tail :: t a -> Maybe (t a)
toList :: t a -> [a]
(|>) :: t a -> a -> t a
QueueA
本身有一个Queue
实例,而不是QueueA
instance Queue QueueA where
-- same as above
对我来说这似乎很清楚:
Queue
类需要两种类型,但您只给了它一种,QueueA a
。我并不完全清楚您试图对这种类型和类执行什么操作,但似乎实例队列(QueueA)a
可以按您的意愿工作?(事实上,在进一步的研究中,我认为我看到了更多的错误——但至少它会让您继续前进。)好的,在我的类定义中,b应该表示队列的类型“a”,以便在类主体中我能够指定函数(|>)和头的返回值(取决于队列类型)。因此,我希望QueueA实际上会被识别为typeclass队列的类型a,约束a被识别为类中的约束b。你证明了我的假设是错误的,你能告诉我怎么做吗?typeclass的目的不是这样的,这样你就可以声明它的单态实例,而这种方式不允许你这样做吗?我把这个问题解释为问如何使用类来定义抽象数据类型的接口,每个实例都提供了一个实现。例如,您也可以为Data.Sequence.Seq
定义一个相当普通的队列
实例,而不是如何将多态容器限制为单态容器。但是,由于队列仅以单态形式依赖于其参数(不像,比方说,函子),我认为应该严格地更灵活地宣布它与fundep的原始方式。然而,使用起来更麻烦。也许我只是不清楚“单态依赖”是什么意思。@chepner认为IsList
和mono-traversable
类。在这种情况下,fundep方法将允许您使用文本
或ByteString
构建队列,但这种方法不会,因为这些类型不能包含任意其他类型。(由于这个原因,在这种特殊情况下,单态方式的限制性比多态方式小。)