我了解到type
同义词是现有类型的新名称。它可以像
type MyChar = Char
但这种用法是什么意思呢?
class HasField a where
type FieldType a :: *
答案 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
但这有两个缺点:
ByteString
和Text
是单态的 - 它们的元素类型分别硬编码为Char8
和Char
。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 k
为Map
)。这是另一天的话题......