这意味着使用'type'是什么意思

时间:2014-10-31 08:18:41

标签: haskell

我了解到type同义词是现有类型的新名称。它可以像

一样使用
type MyChar = Char

但这种用法是什么意思呢?

class HasField a where
    type FieldType a :: *

2 个答案:

答案 0 :(得分:11)

这是一个associated type family,如果您使用该pragma,则由GHC提供的扩展程序

{-# LANGUAGE TypeFamilies #-}

或将参数-XTypeFamilies传递给 GHC GHCi

基本上,它声明了一个类,使得类的每个实例都可以单独定义类型同义词的含义。例如:

data MyDataType = MyDataConstructor Int

instance HasField MyDataType where
    type FieldType MyDataType = Int

答案 1 :(得分:2)

所有这些都有点先进,所以如果你刚刚开始使用Haskell,不要觉得你必须马上理解这一点。

那就是说,我将为Ørjan的答案添加一个简单的例子,想象我们定义了一个这样的类:

-- | Class for types that can be constructed from a list of items.
class Unfoldable t where
    fromList :: [a] -> t a

现在我们可以为各种类型定义实例:

import Data.Set (Set)
import qualified Data.Set as Set

instance Unfoldable [] where
    fromList = id

instance Unfoldable Set where
    fromList = Set.fromList

但这有两个缺点:

  • 它不适用于单态类型:没有元素类型参数的类型。例如,ByteStringText是单态的 - 它们的元素类型分别硬编码为Char8Char
  • 最好有fromList :: Ord k = [(k, v)] -> Map k v, but that definition doesn't support it, because(k,v)is not a type parameter of地图`。

因此,使用TypeFamilies可以改进它:

{-# LANGUAGE TypeFamilies, ConstraintKinds #-}

import Data.Monoid
import Data.Set (Set)
import qualified Data.Set as Set
import Data.Map (Map)
import qualified Data.Map as Map
import Data.Text (Text, pack)
import GHC.Exts (Constraint)

class Monoid m => Unfoldable m where
    type Element m :: *
    type Constraint m :: GHC.Exts.Constraint
    type Constraint m = ()

    fromList :: [Element m] -> m

instance Unfoldable [a] where
    type Element [a] = a
    fromList as = as

instance Ord a => Unfoldable (Set a) where
    type Element (Set a) = a
    type Constraint (Set a) = Ord a
    fromList = Set.fromList

instance Ord k => Unfoldable (Map k v) where
    type Element (Map k v) = (k, v)
    type Constraint (Map k v) = Ord k
    fromList = Map.fromList

instance Unfoldable Text where
    type Element Text = Char
    fromList = pack

查看fromList :: Monoid m => [Element m] -> m的类型。基本上,Element m是一个同义词,其扩展因m的每个不同选择而有所不同:

  • Element [a] := a
  • Element (Map k v) := (k ,v)
  • Element Text := Char

这里的另一个技巧是使用ConstraintKinds来允许每个类实例要求对类型变量进行个性化约束(例如Ord kMap)。这是另一天的话题......