简体   繁体   English

Haskell:类型类可以定义类型(ala类型特征)

[英]Haskell: Can typeclasses define types (ala type traits)

Is it possible to have a type be part of a typeclass? 是否可以将类型作为类型类的一部分? Something like: 就像是:

class KeyTraits v where
    keyType :: *
    key :: v -> keyType

data TableRow = { date :: Date, metaData :: String, value :: Int }

instance KeyTraits TableRow where
    keyType = Date
    key = date

And can these "type-level" functions be used elsewhere? 这些“类型级”功能可以在其他地方使用吗? For example: 例如:

-- automatically deduce the type for the key, from the value type, using
-- the typeclass
data MyMap v = { getMap :: (KeyTraits v) => Map (keyType) v }

I may be doing something completely wrong, but I basically want the ability to define type relationships like the one above (eg Certain values already may have data that can be used as a Key). 我可能正在做一些完全错误的事情,但我基本上希望能够定义类似上面的类型关系(例如,某些值已经可能具有可用作Key的数据)。 If that's not possible, or is difficult, could you suggest a better design that is more idiomatic? 如果那是不可能的,或者很难,你能否提出一个更具惯用性的更好的设计?

Thank you! 谢谢!

Take a look at type families . 看一下类型系列

{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE RankNTypes #-}

class KeyTraits k where
    type KeyType k :: *
    key :: v -> KeyType k

data TableRow = TableRow { date :: Date, metaData :: String, value :: Int }

instance KeyTraits TableRow where
    type KeyType TableRow = Date
    key = date

data MyMap v = MyMap { getMap :: (KeyTraits v) => Map (KeyType v) v }

Type families are exactly what you are looking for, but there is also another way to achieve their functionality, namely multi-parameter type classes with functional dependencies . 类型族正是您所寻找的,但还有另一种实现其功能的方法,即具有功能依赖性的 多参数类型类 With these extensions you code could look like this: 使用这些扩展,您的代码可能如下所示:

{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-}

class KeyTraits v k | v -> k where
    key :: v -> k

data TableRow = { date :: Date, metaData :: String, value :: Int }

instance KeyTraits TableRow Date where
    key = date

Here the associated type migrates to type class parameter, and the relationship between v and k , previously implicit, now becomes explicit with functional dependency. 这里,关联类型迁移到类型类参数,之前隐含的vk之间的关系现在变得明确,具有功能依赖性。

This is completely equivalent to associated types, but IMO provides much more cleaner syntax, especially in functions which use your type class. 这完全等同于关联类型,但IMO提供了更清晰的语法,尤其是在使用类型类的函数中。 Compare: 相比:

getMap :: (KeyTraits v) => Map (KeyType v) v

and

getMap :: (KeyTraits k v) => Map k v

This becomes more apparent when more types and more type classes appear in single type declaration. 当单个类型声明中出现更多类型和更多类型类时,这变得更加明显。

However, type families seem to be preferred by haskell community, and in fact the whole extension is more powerful than MPTC+FD, because type families can be declared without type classes, and there are also data families. 但是,类型族似乎是haskell社区的首选,事实上整个扩展比MPTC + FD更强大,因为类型族可以声明没有类型类,并且还有数据族。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM