在下面的代码中,我认为函数f
的概念是合理的,当然,我们不知道D
的第一个元素的确切类型,但我们知道它是某些T a
a
。
{-# LANGUAGE GADTs #-}
{-# LANGUAGE RankNTypes #-}
data T a
data D where
D1 :: T a -> D
D2 :: T Bool -> D
f :: D -> (forall a. T a)
f (D1 x) = x
f (D2 x) = x
main = return ()
但是,GHC会抛出以下错误:
GADTTypes.hs:11:12: error:
• Couldn't match type ‘a1’ with ‘a’
‘a1’ is a rigid type variable bound by
a pattern with constructor: D1 :: forall a. T a -> D,
in an equation for ‘f’
at GADTTypes.hs:11:4
‘a’ is a rigid type variable bound by
the type signature for:
f :: forall a. D -> T a
at GADTTypes.hs:11:1
Expected type: T a
Actual type: T a1
• In the expression: x
In an equation for ‘f’: f (D1 x) = x
• Relevant bindings include x :: T a1 (bound at GADTTypes.hs:11:7)
GADTTypes.hs:12:12: error:
• Couldn't match type ‘a’ with ‘Bool’
‘a’ is a rigid type variable bound by
the type signature for:
f :: forall a. D -> T a
at GADTTypes.hs:11:1
Expected type: T a
Actual type: T Bool
• In the expression: x
In an equation for ‘f’: f (D2 x) = x
只是想知道我想要实现的是什么以及如何修复我的代码?
答案 0 :(得分:2)
您的签名声称您可以为T a
我想到的所有a
返回D2
。但是,如果我通过T Int
并要求forall
您将无法提供,那么您的签名就是谎言;)
我认为你在这里误解exists
为<button type="button" id="save" class="submit">Save</button>
<button type="button" id="submit" class="submit">Submit</button>
<button type="button" id="tempAdd" class="submit">Temporarily Add</button>
。但是,存在类型可以通过Universal类型(forall)实现,如Haskell Wiki所示。
答案 1 :(得分:2)
Haskell没有exists a. T a
,这是你需要的,但你可以为此声明自己的类型。
data T a
data D where
D1 :: T a -> D
D2 :: T Bool -> D
data ExT where
ExT :: T a -> ExT
f :: D -> ExT
f (D1 x) = ExT x
f (D2 x) = ExT x
然后,如果你有
g :: T a -> ...
并且您希望撰写g (f x)
,而您需要使用
case f x of
ExT y -> g y
请注意,显然等效的以下代码将不类型检查,而是(因为没有exists
类型)。
g (case f x of
ExT y -> y)
如果您愿意,您可以为此创建自己的帮助:
help :: (forall a. T a -> b) -> ExT -> b
help h (ExT x) = h x
-- example
foo x = help g (f x)
这会使语法更接近普通g (f x)
。