键入`Eq`的等效系列?

时间:2017-05-10 02:36:35

标签: haskell

Type Families with Class显示:

enter image description here

由于我不完全理解,此幻灯片显示了实现X-Real-IP的两种方式:通过类型类或类型族。

我熟悉类型类,因此实现了Eq

MyEq

但是,当我尝试定义class MyEq a where eq :: a -> a -> Bool 版本时,它无法编译:

type family

由于:

data Defined = Yes | No

type family IsEq (a :: *) :: Defined    

请说明如何实施TypeEq.hs:30:30: error: • Type constructor ‘Defined’ cannot be used here (Perhaps you intended to use DataKinds) • In the kind ‘Defined’ 类型的type family版本。 另外,请展示这样一个Eq实例的实现(如果这个甚至是正确的词)。

2 个答案:

答案 0 :(得分:6)

这有点整洁,很高兴偶然发现了这一点。对于感兴趣的人,here是幻灯片,here是纸。这是需要一些语言扩展的常见情况。

{-# LANGUAGE DataKinds, TypeFamilies, TypeOperators, ConstraintKinds #-}

data Defined = Yes | No

type family IsEq (a :: *) :: Defined

type Eq a = IsEq a ~ Yes

然后,"实施"这是像

这样的例子
type instance IsEq () = Yes      -- '()' is an instance of 'Eq'
type instance IsEq Int = Yes     -- 'Int' is an instance of 'Eq'
type instance IsEq [a] = IsEq a  -- '[a]' is an instance of 'Eq' is 'a' is

你可以尝试"他们出现在GHCi:

ghci> :kind! IsEq [Int]
IsEq [Int] :: Defined
= Yes

但纸张和幻灯片并没有真正过分担心实际提供相等功能。 (它提到将其存储在Yes的字段中)。那么,如果它还没有准备好提供类方法,为什么这很有趣呢?因为

  • 它提供了比重叠类更好的机制
  • 回溯搜索比使用类型类更容易
  • 它可以提前出现错误消息(在No构造函数中编码为字段)

答案 1 :(得分:1)

尝试添加DataKinds作为语言扩展名(例如,在"语言" pragma下的文件顶部),如错误消息所示。

我还没看过这个话题,但是iiuc,Defined只是Bool,其中YesTrue。因此,如果你启用DataKinds,你可以使用IsEq a ~ 'True(和True之前的撇号意味着"这是一种类型")。

一些背景知识:此扩展程序的作用是"引发"任何代数数据类型的每个值(即声明为data,但不是GADTs,iiuc)为其自己的类型;然后将每种类型提升到它自己的类型中("种类"在Haskell中是"类型类型"),即不是"种类*" (发音为" kind star"),这是运行时存在的普通Haskell值。

顺便说一句:

[Bool] :: *表示"留置权列表是一种类型"。并且[] :: * -> *表示列表的类型构造函数具有类型"类型以键入",即"一旦您为List提供单个类型,您将返回类型"。