在Haskell中返回另一个Typeclass的Typeclass方法
我的任务是在Haskell中定义2个TypeClass。一个是简单的-它实现Ord,并有一个方法将给定类型转换为int。类似如下:在Haskell中返回另一个Typeclass的Typeclass方法,haskell,typeclass,Haskell,Typeclass,我的任务是在Haskell中定义2个TypeClass。一个是简单的-它实现Ord,并有一个方法将给定类型转换为int。类似如下: class (Ord a) => Id a where toInt :: a -> Int class HasId a where getId :: a -> Id a 但是我有另一个类型类HasId,它有一个getId方法。此方法应返回Id typeclass。所以我写了这样的东西: class (Ord a) => Id a
class (Ord a) => Id a where
toInt :: a -> Int
class HasId a where
getId :: a -> Id a
但是我有另一个类型类HasId,它有一个getId方法。此方法应返回Id typeclass。所以我写了这样的东西:
class (Ord a) => Id a where
toInt :: a -> Int
class HasId a where
getId :: a -> Id a
我遇到了一个我不知道如何解决的错误
• Expected kind ‘* -> Constraint’, but ‘Int’ has kind ‘*’
• In the class declaration for ‘HasId’
|
| class (Int a) => HasId a where | ^^^^^
• Expected a type, but ‘Id a’ has kind ‘Constraint’
• In the type signature: getId :: a -> Id a
In the class declaration for ‘HasId’
|
| getId :: a -> Id a |
有人能告诉我如何在别人的typeclass方法中返回typeclass吗?
我应该首先实现Id typeclass的某个实例吗?您声明返回值为HKT
Id a
,但您需要的是另一个类型,受typeclassId
的约束
您需要的不是
getId::a->ida
,而是getId::idb=>a->b
了解Haskell类与OO语言中的类非常不同,这一点很重要。它是一个类型类,即它“将一组类型组合在一起”,而OO类将一组值组合在一起。依我看,OO类是一种类型(包含值),但Haskell类实际上更像是一种类型
现在,函数/方法总是将值作为参数,并将值作为结果返回。但它不能返回类型,也不能返回“类型类的值”,因为根本没有这样的东西
相反,使用类型类的方法是:编写一个多态函数,即一个接受或生成未指定类型值的函数。这就是类型变量的用途。通常,多态签名意味着函数可以处理任何类型的值,比如
length :: [a] -> Int
它接受一个列表,不关心其元素的类型。但是你说你确实有点在乎使用什么类型,也就是说,你要求它们在类中。这是一个约束,它是用=>
符号编写的toInt
实际具有签名(由类声明自动生成)
坦率地说,我怀疑这是否真的是你想要的。如果对Id a
所能做的只是将其转换为Int
,那么不管a
参数是什么,结果实际上就是一个Int
(只是带有一个类型注释,指示该Id属于哪种类型的对象)。因此,代替<代码> ID <代码>类,应该考虑有<代码> ID <代码>类型
然后,你有更明智的类型
toInt :: Id' a -> Int
不需要任何约束
newtype
与OO类更为相似,因为它实际上定义了一个具体类型,其中包含可以传递的值
getId
方法也是一个受约束的多态函数,它可以获取“具有Id
”的内容并返回该Id。在这种情况下,类是有意义的(因为可以使用不同的数据结构以不同的方式存储它们的Id)。这实际上是
class HasId a where
getId :: a -> Id' a
根据,使用原始的Id
类来定义HasId
确实也很方便,只是它没有多大意义Id
是可以用作标识符的所有类型的类。您可以表示getId
可以生成任何此类类型的Id:
class HasId a where
getId :: Id b => a -> b
请注意,结果Id类型现在完全独立于要计算其Id的对象类型<代码>b
始终可以是任何Id类型。正如我所说的,这是没有意义的:为什么您需要大量不同的类型来表示ID,但需要所有的HasId
类型来支持它们
事实上,这无法按现状实现,因为没有任何机制允许您生成任意Id
类型的Id。这需要一种额外的方法
class Id a where
toInt :: a -> Int
fromInt :: Int -> a
现在你可以做了
class HasId a where
getId :: Id b => a -> b
data SomeObj { objName :: String
, objId :: Int }
instance HasId SomeObj where
getId (SomeObj _ i) = fromInt i
但是,如果您要求任何
Id
类型都可以从Int
和转换为Int
,那么这些类型必须与Int
本身同构。因此,newtypeid'a
方法几乎肯定更好。这可能会进行类型检查,但我怀疑它是否真的有效。问题中给出的Id
类使得getId::Id b=>a->b
基本上不可能实现。谢谢你的扩展答案!非常感谢你的帮助。事实上,我明天的考试需要它,所以再次非常感谢:)