【发布时间】:2014-10-31 08:18:40
【问题描述】:
我了解到type 同义词是现有类型的新名称。可以这样使用
type MyChar = Char
但是这样的用法是什么意思呢?
class HasField a where
type FieldType a :: *
【问题讨论】:
标签: haskell
我了解到type 同义词是现有类型的新名称。可以这样使用
type MyChar = Char
但是这样的用法是什么意思呢?
class HasField a where
type FieldType a :: *
【问题讨论】:
标签: haskell
这是一个associated type family,如果您使用编译指示,则由 GHC 提供的扩展
{-# LANGUAGE TypeFamilies #-}
或将参数-XTypeFamilies 传递给GHC 或GHCi。
基本上,它声明了一个类,这样类的每个实例都可以单独定义类型同义词的含义。例如:
data MyDataType = MyDataConstructor Int
instance HasField MyDataType where
type FieldType MyDataType = Int
【讨论】:
所有这些都有些高级,所以如果你刚刚开始使用 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 ofMap`,那就太好了。所以使用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] := aElement (Map k v) := (k ,v)Element Text := Char这里的另一个技巧是使用ConstraintKinds 允许每个类实例要求对类型变量进行个性化约束(例如,Ord k 用于Map)。这是另一天的话题......
【讨论】:
Constraint 类型,但你似乎没有使用它。我猜你想要它作为对fromList 的约束? (2) 如果你坚持使用冲突名称Constraint,我认为GHC.Exts 应该被导入qualified,即使这在定义实例时恰好起作用。