在Haskell中,如果我有一个像
这样的界面class Eq a => Lol l a b where
...
我应该如何声明简单实例? 如果我尝试像
那样的话class Lol1 a b
instance Lol Lol1 A B
它抱怨说Lol的第一个参数应该有类型* - > * - > *而Lol1有种类
* -> * -> Constraint
答案 0 :(得分:2)
你得到的错误是一种不匹配。种类是类型的“类型”。例如,Int
具有*
种类。 *
用于表示任何haskell值类型,Int
s,Bool
s,等等。
所以你正在寻找那种* -> * -> *
的东西。这会收集2件类*
并返回*
。一个例子是Either
。
问题是您的类型类Lol1
没有* -> * -> *
类型,它意味着在=>
的左侧使用,那些东西有Constraint
类a ~ Int
1}}。像这样的其他东西是等式约束,instance Foo (a ~ Int)
或隐式参数。
因此,这导致了不可避免的结论,即您不能将类用作其他类的参数,如下所示。它永远不会被证实。这就像说 class Foo k where
foo :: ... => k a -> ...
-- Or in general, On the right side of an =>
foo' :: ... => Foo Foo -> ..
。
data Lol1 a b = ...
所以你必须使用数据类型,
...
如果没有Lol
的更多代码,我无法提供有关{{1}}应该是什么的任何详细信息。
答案 1 :(得分:1)
您是否阅读过learnyouahaskell?
特别是关于typeclasses的部分以及关于kinds的部分应该对您的情况非常有帮助。
答案 2 :(得分:0)
在不知道程序的整个范围的情况下,我不能说这是否是您想要的解决方案。但是你确实可以使用类并将它们视为类实例中的类型。
{-# LANGUAGE
MultiParamTypeClasses,
KindSignatures,
ConstraintKinds,
FlexibleInstances,
UndecidableInstances
#-}
import GHC.Prim (Constraint)
class Lol1 a b -- Lol1 has kind * -> * -> Constraint
class Lol2 a -- Lol2 has kind * -> Constraint
-- Note the explicit 'kind' signature for type var 'l'. This is necessary
class Eq a => Lol (l :: * -> * -> Constraint) a b where
instance Eq b => Lol Lol1 b c
-- instance Eq b => Lol Lol2 b c -- won't work
data A; data B
你可以用类'type'变量做的唯一事情就是用它来约束其他类型变量,或者把它传递给另一个类。
class (l a b) => Lol (l :: * -> * -> Constraint) a b where
instance Lol1 a b -- removing this breaks the line below
instance Lol Lol1 a b