【问题标题】:What does this mean by using 'type'使用“类型”是什么意思
【发布时间】:2014-10-31 08:18:40
【问题描述】:

我了解到type 同义词是现有类型的新名称。可以这样使用

type MyChar = Char

但是这样的用法是什么意思呢?

class HasField a where
    type FieldType a :: *

【问题讨论】:

    标签: haskell


    【解决方案1】:

    这是一个associated type family,如果您使用编译指示,则由 GHC 提供的扩展

    {-# LANGUAGE TypeFamilies #-}
    

    或将参数-XTypeFamilies 传递给GHCGHCi

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

    data MyDataType = MyDataConstructor Int
    
    instance HasField MyDataType where
        type FieldType MyDataType = Int
    

    【讨论】:

    • 我现在看到了,谢谢!我认为在开始阅读一些开源代码之前,最好先阅读 GHC 用户指南...
    【解决方案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 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] := a
    • Element (Map k v) := (k ,v)
    • Element Text := Char

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

    【讨论】:

    • (1) 我看到你定义了Constraint 类型,但你似乎没有使用它。我猜你想要它作为对fromList 的约束? (2) 如果你坚持使用冲突名称Constraint,我认为GHC.Exts 应该被导入qualified,即使这在定义实例时恰好起作用。
    猜你喜欢
    • 2015-02-20
    • 1970-01-01
    • 2016-09-15
    • 2015-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多