【发布时间】:2017-03-16 03:47:01
【问题描述】:
在下面的代码中,我试图匹配 GADT 构造函数 Cons 以让编译器看到 xs 是非空的:
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeOperators #-}
import Data.Typeable
data Foo (ts :: [*]) where
Nil :: Foo '[]
Cons :: (Typeable t) => Foo ts -> Foo ( t ': ts)
foo :: Foo xs -> IO ()
foo Nil = print "done"
foo (Cons rest :: Foo (y ': ys)) = do
print $ show $ typeRep (Proxy::Proxy y)
foo rest
很遗憾,这个简单的示例无法使用 GHC 8 进行编译:
• Couldn't match type ‘xs’ with ‘y : ys’
‘xs’ is a rigid type variable bound by
the type signature for:
foo :: forall (xs :: [*]). Foo xs -> IO ()
Expected type: Foo (y : ys)
Actual type: Foo xs
• When checking that the pattern signature: Foo (y : ys)
fits the type of its context: Foo xs
In the pattern: Cons rest :: Foo (y : ys)
In an equation for ‘foo’:
foo (Cons rest :: Foo (y : ys))
= print $ (show $ typeRep (Proxy :: Proxy y))
我知道使用 GADT 进行类型推断可能会很棘手(例如,#9695、#10195、#10338),但这如此很简单...
我需要做些什么来让 GHC 相信,当我在 Cons 上匹配时,GADT 参数至少有一个元素?
【问题讨论】:
-
为什么不简单地拥有
foo :: Foo (x ': xs) -> ()? -
当然这个例子是简化的,但是
foo里面确实有一些递归调用。我需要匹配Cons案例或Nil案例(省略),当然还有Nil :: Foo '[]。我真的需要 GHC 根据模式匹配找出xs ~ (y ': ys)。 -
@Alec 我改进了这个例子来说明我为什么要问我在问什么。当我过度简化示例时,我讨厌它......
-
谢谢!作为旁注,this 在这里非常有用。 :)