【问题标题】:Haskell: Can typeclasses define types (ala type traits)Haskell:类型类可以定义类型(ala类型特征)
【发布时间】:2013-06-28 05:43:26
【问题描述】:

类型可以成为类型类的一部分吗?比如:

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

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

instance KeyTraits TableRow where
    keyType = Date
    key = date

这些“类型级”函数可以在其他地方使用吗?例如:

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

我可能做错了什么,但我基本上希望能够像上面那样定义类型关系(例如,某些值可能已经有可以用作键的数据)。如果这不可能或很难,您能否提出一个更符合习惯的更好设计?

谢谢!

【问题讨论】:

    标签: haskell typeclass


    【解决方案1】:

    看看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 }
    

    【讨论】:

      【解决方案2】:

      类型族正是您正在寻找的,但还有另一种实现其功能的方法,即multi-parameter type classesfunctional dependencies。使用这些扩展,您的代码可能如下所示:

      {-# 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
      

      这里关联类型迁移到类型类参数,vk 之间的关系,以前是隐式的,现在通过函数依赖变得显式。

      这完全等同于关联类型,但 IMO 提供了更简洁的语法,尤其是在使用您的类型类的函数中。比较:

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

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

      当更多类型和更多类型类出现在单个类型声明中时,这一点变得更加明显。

      然而,类型族似乎更受haskell社区的青睐,实际上整个扩展比MPTC+FD更强大,因为类型族可以在没有类型类的情况下声明,而且还有数据族。

      【讨论】:

      • 非常感谢您提供的替代方案!尽管其他答案与问题标题更直接相关,但您的解决方案同样相关。
      • 我的印象是 MPTC+FD 在某些具有复杂依赖关系的边缘情况下比 TF 更具表现力...
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-03-30
      • 2017-03-15
      • 2014-10-07
      • 1970-01-01
      • 1970-01-01
      • 2016-07-31
      • 1970-01-01
      相关资源
      最近更新 更多