非单射闭式族
Non-Injective Closed Type Family
我有这段公认的人为设计的代码块
{-# LANGUAGE DataKinds, TypeFamilies #-}
data Foo = Foo
type family Id (n :: Foo) a where
Id 'Foo a = a
data Bar (n :: Foo) = Bar
class Dispatch (n :: Foo) where
consume :: Id n a -> Bar n -> a
consume' :: Dispatch n => Id n [Bool] -> Bar n -> [Bool]
consume' = consume
consume'' :: Dispatch n => Id n [Bool] -> Bar n -> Bool
consume'' g x = and (consume' g x)
这可以编译并且工作正常。但是,如果我将最终的 consume''
定义替换为
consume'' :: Dispatch n => Id n [Bool] -> Bar n -> Bool
consume'' g x = and (consume g x)
(注意 consume
而不是 consume'
),然后我得到一个错误
noinject.hs:17:30: error:
• Couldn't match expected type ‘Id n (t0 Bool)’
with actual type ‘Id n [Bool]’
NB: ‘Id’ is a non-injective type family
The type variable ‘t0’ is ambiguous
• In the first argument of ‘consume’, namely ‘g’
In the first argument of ‘and’, namely ‘(consume g x)’
In the expression: and (consume g x)
• Relevant bindings include
x :: Bar n (bound at noinject.hs:17:13)
g :: Id n [Bool] (bound at noinject.hs:17:11)
consume'' :: Id n [Bool] -> Bar n -> Bool
(bound at noinject.hs:17:1)
|
17 | consume'' g x = and (consume g x)
| ^
Failed, no modules loaded.
如果我们假设 Id
是非单射的,那么会发生错误,因为 consume
可以专门化为 consume :: Id n (t0 Bool) -> Bar n -> t0 Bool
,对于一些不是单射的可折叠 t0
[]
。我明白这么多。我的问题是:为什么 Id
而不是 实际上是单射的。它有两个参数:第一个参数只有一个有效值,而 Id
在第二个参数中显然是单射的,那么为什么 GHC 认为这是一个非单射族?
Injective type families 是类型族之上的单独扩展,您需要特殊的语法来将类型族声明为一个。无法推断单射性。
我有这段公认的人为设计的代码块
{-# LANGUAGE DataKinds, TypeFamilies #-}
data Foo = Foo
type family Id (n :: Foo) a where
Id 'Foo a = a
data Bar (n :: Foo) = Bar
class Dispatch (n :: Foo) where
consume :: Id n a -> Bar n -> a
consume' :: Dispatch n => Id n [Bool] -> Bar n -> [Bool]
consume' = consume
consume'' :: Dispatch n => Id n [Bool] -> Bar n -> Bool
consume'' g x = and (consume' g x)
这可以编译并且工作正常。但是,如果我将最终的 consume''
定义替换为
consume'' :: Dispatch n => Id n [Bool] -> Bar n -> Bool
consume'' g x = and (consume g x)
(注意 consume
而不是 consume'
),然后我得到一个错误
noinject.hs:17:30: error:
• Couldn't match expected type ‘Id n (t0 Bool)’
with actual type ‘Id n [Bool]’
NB: ‘Id’ is a non-injective type family
The type variable ‘t0’ is ambiguous
• In the first argument of ‘consume’, namely ‘g’
In the first argument of ‘and’, namely ‘(consume g x)’
In the expression: and (consume g x)
• Relevant bindings include
x :: Bar n (bound at noinject.hs:17:13)
g :: Id n [Bool] (bound at noinject.hs:17:11)
consume'' :: Id n [Bool] -> Bar n -> Bool
(bound at noinject.hs:17:1)
|
17 | consume'' g x = and (consume g x)
| ^
Failed, no modules loaded.
如果我们假设 Id
是非单射的,那么会发生错误,因为 consume
可以专门化为 consume :: Id n (t0 Bool) -> Bar n -> t0 Bool
,对于一些不是单射的可折叠 t0
[]
。我明白这么多。我的问题是:为什么 Id
而不是 实际上是单射的。它有两个参数:第一个参数只有一个有效值,而 Id
在第二个参数中显然是单射的,那么为什么 GHC 认为这是一个非单射族?
Injective type families 是类型族之上的单独扩展,您需要特殊的语法来将类型族声明为一个。无法推断单射性。