gpt4 book ai didi

haskell - 简而言之,'type family' 与 'data family' ?

转载 作者:行者123 更新时间:2023-12-03 06:07:23 27 4
gpt4 key购买 nike

我对如何在数据族类型族之间进行选择感到困惑。维基页面TypeFamilies涉及很多细节。有时,它在散文中非正式地将 Haskell 的数据族称为“类型族”,但当然 Haskell 中也有类型族

有一个简单的示例,显示了两个版本的代码的显示位置,区别仅在于声明的是数据系列还是类型系列:

-- BAD: f is too ambiguous, due to non-injectivity
-- type family F a

-- OK
data family F a

f :: F a -> F a
f = undefined

g :: F Int -> F Int
g x = f x
这里的

typedata含义相同,但是type family版本无法进行类型检查,而data family 版本很好,因为 data family “创建新类型,因此是单射的”(维基页面说)。

我从这一切中得到的结论是“对于简单的情况尝试数据族,如果它不够强大,那么尝试类型族”。这很好,但我想更好地理解它。是否有我可以遵循的维恩图或决策树来区分何时使用哪个?

最佳答案

(将评论中的有用信息提升为答案。)

独立声明与类内声明

声明类型族和/或数据族的两种语法上不同的方法,在语义上是等效的:

独立:

type family Foo
data family Bar

或者作为类型类的一部分:

class C where
type Foo
data Bar

都声明了一个类型族,但在类型类中 family部分由 class 暗示上下文,因此 GHC/Haskell 缩写了声明。

“新类型”与“类型同义词”/“类型别名”

data family F创建一个新类型,类似于 data F = ...创建一个新类型。

type family F不创建新类型,类似于 type F = Bar Baz 不会创建新类型(它只是为现有类型创建别名/同义词)。

type family 的非注入(inject)性示例

来自 Data.MonoTraversable.Element 的示例(稍作修改) :

import Data.ByteString as S
import Data.ByteString.Lazy as L

-- Declare a family of type synonyms, called `Element`
-- `Element` has kind `* -> *`; it takes one parameter, which we call `container`
type family Element container

-- ByteString is a container for Word8, so...
-- The Element of a `S.ByteString` is a `Word8`
type instance Element S.ByteString = Word8

-- and the Element of a `L.ByteString` is also `Word8`
type instance Element L.ByteString = Word8

在类型族中,方程的右侧 Word8命名现有类型;左侧的事物创建了新的同义词:Element S.ByteStringElement L.ByteString

拥有同义词意味着我们可以互换 Element Data.ByteStringWord8 :

-- `w` is a Word8....
>let w = 0::Word8

-- ... and also an `Element L.ByteString`
>:t w :: Element L.ByteString
w :: Element L.ByteString :: Word8

-- ... and also an `Element S.ByteString`
>:t w :: Element S.ByteString
w :: Element S.ByteString :: Word8

-- but not an `Int`
>:t w :: Int
Couldn't match expected type `Int' with actual type `Word8'

这些类型同义词是“非内射的”(“单向”),因此是不可逆的。

-- As before, `Word8` matches `Element L.ByteString` ...
>(0::Word8)::(Element L.ByteString)

-- .. but GHC can't infer which `a` is the `Element` of (`L.ByteString` or `S.ByteString` ?):

>(w)::(Element a)
Couldn't match expected type `Element a'
with actual type `Element a0'
NB: `Element' is a type function, and may not be injective
The type variable `a0' is ambiguous

更糟糕的是,GHC 甚至无法解决明确的情况!:

type instance Element Int = Bool
> True::(Element a)
> NB: `Element' is a type function, and may not be injective

注意“可能不是”的使用!我认为 GHC 很保守,拒绝检查 Element 是否有效。确实是内射的。 (也许是因为程序员可以在导入预编译模块后添加另一个type instance,从而增加歧义。

data family 的单射性示例

相反:在数据族中,每个右侧都包含一个唯一的构造函数,因此定义是单射(“可逆”)方程。

-- Declare a list-like data family
data family XList a

-- Declare a list-like instance for Char
data instance XList Char = XCons Char (XList Char) | XNil

-- Declare a number-like instance for ()
data instance XList () = XListUnit Int

-- ERROR: "Multiple declarations of `XListUnit'"
data instance XList () = XListUnit Bool
-- (Note: GHCI accepts this; the new declaration just replaces the previous one.)

data family ,看到右侧的构造函数名称( XConsXListUnit )足以让类型推断器知道我们必须使用 XList ()不是XList Char 。由于构造函数名称是唯一的,因此这些定义是单射/可逆的。

如果 type “just”声明了一个同义词,为什么它在语义上有用?

通常,type同义词只是缩写,但是type系列同义词增加了功能:它们可以使简单类型 (kind * ) 成为“将 kind * -> * 应用于参数的类型”的同义词:

type instance F A = B

使B匹配F a 。例如,这在 Data.MonoTraversable 中使用。制作一个简单的类型Word8匹配 Element a -> a 类型的函数( Element 已在上面定义)。

例如,(有点傻),假设我们有一个 const 的版本仅适用于“相关”类型:

> class Const a where constE :: (Element a) -> a -> (Element a)
> instance Const S.ByteString where constE = const

> constE (0::Word8) undefined
ERROR: Couldn't match expected type `Word8' with actual type `Element a0'

-- By providing a match `a = S.ByteString`, `Word8` matches `(Element S.ByteString)`
> constE (0::Word8) (undefined::S.ByteString)
0

-- impossible, since `Char` cannot match `Element a` under our current definitions.
> constE 'x' undefined

关于haskell - 简而言之,'type family' 与 'data family' ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20870432/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com