Haskell GHC能够';我不能推断出这种类型吗?
GHC拒绝该计划Haskell GHC能够';我不能推断出这种类型吗?,haskell,type-inference,Haskell,Type Inference,GHC拒绝该计划 {-# LANGUAGE GADTs #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE TypeOperators #-} import GHC.TypeLits data Foo = Foo data Bar = Bar data (:::) :: * -> * -> * where (:=) :: sy -> t -> sy ::: t
{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}
import GHC.TypeLits
data Foo = Foo
data Bar = Bar
data (:::) :: * -> * -> * where
(:=) :: sy -> t -> sy ::: t
data Rec :: [*] -> * where
RNil :: Rec '[]
(:&) :: (sy ::: ty) -> Rec xs -> Rec ((sy ::: ty) ': xs)
infix 3 :=
infixr 2 :&
baz :: Num ty => Rec [Foo ::: String, Bar ::: ty]
baz = Foo := "foo" :& Bar := 1 :& RNil
--bang :: (String, Integer)
bang = case baz of
(Foo := a :& Bar := b :& RNil) -> (a, b)
与
,使用类型注释,它可以正常工作。我在网上找到的所有关于不可触及类型变量和GADT的答案都断言类型推断是不可能的,或者至少是难以解决的,但在这种情况下,GHC显然掌握了类型
(字符串,整数)
,它只是拒绝统一。也许您最初的GADT可以作为不使用GADT的东西的糖,如以下所示(有效):
如果你是单形态的baz,它能起作用吗?这是一个很好的建议,我将仔细研究它与我的其他计划之间的相互作用,但它并不能真正回答我的问题:)嗯,其结果之一是“baz”的推断类型现在不是一个很好的
Rec
,它的元素以类型参数的形式列出,例如乙烯基,而是一个类型级别的列表、列表、记录等。这是我绝对想要的,我会牺牲模式匹配。不过,它可以很好地与一个数据系列配合使用,而这最终可能是我想要的。这个示例表明,您不需要为数据记录
使用GADT的所有功能,但您仍然需要为类型推断付出代价。。。。因此,在保持类型推断为良好的普通ADT的同时,可能还有一些空间使用像GADT这样的好语法。如果您编写一个类在两者之间进行转换,似乎您可以同时使用这两种语法
Rec2.hs:25:44:
Couldn't match type ‛t’ with ‛(String, Integer)’
‛t’ is untouchable
inside the constraints (xs1 ~ '[] *)
bound by a pattern with constructor
RNil :: Rec ('[] *),
in a case alternative
at Rec2.hs:25:35-38
‛t’ is a rigid type variable bound by
the inferred type of bang :: t at Rec2.hs:24:1
Expected type: t
Actual type: (ty, ty1)
Relevant bindings include bang :: t (bound at Rec2.hs:24:1)
In the expression: (a, b)
In a case alternative: (Foo := a :& Bar := b :& RNil) -> (a, b)
In the expression:
case baz of { (Foo := a :& Bar := b :& RNil) -> (a, b) }
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
import GHC.TypeLits
data Foo = Foo
data Bar = Bar
data (:::) sy t = (:=) sy t
data RNil = RNil
data (:&) a b = a :& b
type family Rec (xs :: [*]) :: *
type instance Rec (x ': xs) = x :& Rec xs
type instance Rec '[] = RNil
infix 3 :=
infixr 2 :&
baz :: Num ty => Rec [Foo ::: String, Bar ::: ty]
baz = Foo := "foo" :& Bar := 1 :& RNil
bang = case baz of
( Foo := a :& Bar := b :& RNil) -> (a, b)