在类和实例声明中键入关键字

Cli*_*ton 6 haskell

我正在查看源代码Data.Has并试图弄清楚它是如何工作的.我相信下面的代码是为了让别人"加入"两个值,说a :: Ab :: B成同时具有的功能的新的价值ab.

我特别不明白type类和实例声明中的含义.

另外我不知道~下面的符号是什么意思.

有人可以从Data.Has.TypeList解释下面的代码吗?

-- | Provides type-list functionality

module Data.Has.TypeList where

import Control.Applicative
import Data.Monoid (Monoid (..))
import Test.QuickCheck (Arbitrary (..), CoArbitrary (..))
import Data.Typeable
import Data.Data
-- | Cons a type onto type-list.
data a ::: b = a ::: b deriving (Show,Eq,Ord,Read,Bounded,Typeable,Data)

-- | The empty type-list.
data TyNil = TyNil deriving (Read,Typeable,Data)

-- | Appends a type-list and another.
class Append a b where
    type a :++: b
    (.++.) :: a -> b -> a :++: b
infixr 5 :++:

-- Implementation of Append

instance Append TyNil b where
    type TyNil :++: b = b
    _ .++. b = b

instance (Append y b) => Append (x ::: y) b where
    type (x ::: y) :++: b = x ::: (y :++: b)
    ~(x ::: y) .++. b = x ::: (y .++. b)
Run Code Online (Sandbox Code Playgroud)

Vla*_*eev 9

type类型类和实例声明中的语法是TypeFamilies扩展的一部分.类型族可以被认为是从类型到类型的函数.Haskell wiki中有关于类型和数据系列的详细解释(参见链接).

应用于类型类,类型族成为关联类型.在这方面,他们非常接近FunctionalDependencies,也就是说,他们允许毫无根据的实例解析.在GHC手册中充分解释了对此的需求.

示例中的类型定义非常简单.:::是2元组的另一个名称(一对值),与TyNil单元类型同构().

我将尝试阅读类和实例声明,以便明确它们的含义.

class Append a b where
    type a :++: b
    (.++.) :: a -> b -> a :++: b
infixr 5 :++:
Run Code Online (Sandbox Code Playgroud)

声明多参数类型类Append a b与相关联的类型a :++: b和一个方法的功能(.++.)这需要的类型的值ab并产生类型的值a :++: b.我们还设置(.++.)为与优先级5正确关联.

instance Append TyNil b where
    type TyNil :++: b = b
    _ .++. b = b
Run Code Online (Sandbox Code Playgroud)

声明Append a b具有固定的第一个参数(TyNil)和任意第二个参数(b)的实例,其中关联的类型a :++: b(在这种情况下它是TyNil :++: b)被声明为等于b.(我不会描述用什么方法做,这很清楚).

instance (Append y b) => Append (x ::: y) b where
    type (x ::: y) :++: b = x ::: (y :++: b)
    ~(x ::: y) .++. b = x ::: (y .++. b)
Run Code Online (Sandbox Code Playgroud)

声明的实例Append a b与表单中第一个参数x ::: y为任意的xy和任意的第二个参数b给出的,已经有实例Append y b声明.关联类型a :++: b(此处(x ::: y) :++: b,显然)声明等于x ::: (y :++: b).方法定义在这里也很清楚:它接受一对值和另一个值,并构造另一对,其中第一个元素与第一个参数相同,第二个元素是第一个参数的第二个元素,第二个参数与.++.方法相结合.我们被允许使用.++.因为Append y b约束

这些是(.++.)类声明和实例声明中方法的类型签名:

(.++.) ::               a       -> b -> a :++: b
(.++.) ::               TyNil   -> b -> b
(.++.) :: Append y b => x ::: y -> b -> x ::: (y :++: b)
Run Code Online (Sandbox Code Playgroud)

请注意,在每个实例中,非常抽象a :++: b转换为更具体的类型.它b在第一种情况下很简单,而且更复杂x ::: (y :++: b),本身就是用它来写的:++:.

需要相关联的类型的,例如声明告诉型系统,该系统有一些类型(a :++: b在这种情况下),其唯一地确定通过ab单独.也就是说,如果typechecker知道某些表达式ab类型等于,比如,IntDouble,和:

  1. 有一个约束Append a b;
  2. 有一个类型类实例Append Int Double,声明了相关的类型,比如,as type Int :++: Double = String,

那么类型检查员会知道,如果他遇到类型,a :++: b它会知道实际上这种类型是String.

至于~它被称为'懒模式匹配'.这里有很清楚的解释.

随意询问是否仍然不清楚.