Haskell 非内射闭型族

Haskell 非内射闭型族,haskell,type-families,injective-function,Haskell,Type Families,Injective Function,我有一段公认是人为设计的代码 {-# 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

我有一段公认是人为设计的代码

{-# 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'' :: 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认为这是一个非内射的族呢?

是类型族之上的一个单独扩展,需要特殊的语法将类型族声明为一个。内射性无法推断。

我只想补充一点,在我有限的经验中,内射型家族从未解决过我期望他们解决的任何问题;-)。也许OP是他们工作的案例之一。我记得一些琐碎的例子,比如
f::fa~fb=>a->b;f x=x
由于在类型检查过程中内射能力未被充分利用,因此无法正常工作。@chi不幸的是,您是对的,GHC似乎仍然不接受我的类型为内射的,即使带有显式注释。不过,这确实回答了我的问题,所以谢谢你们两位的帮助!:)