从多个构造函数中提取大多数常规类型

时间:2017-01-19 09:10:17

标签: haskell

在下面的代码中,我认为函数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

只是想知道我想要实现的是什么以及如何修复我的代码?

2 个答案:

答案 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)

相关问题