2016-05-12 49 views
1

我有一个名为Showable喜欢这类型:有没有一种方法来表示函数在GHC的Haskell中显示的解压缩?

{-# LANGUAGE ExistentialQuantification #-} 
    {-# LANGUAGE ExplicitForAll #-} 
    data Showable = forall a . Show a => Showable a 

然后使该包装是微不足道的功能。我只需要写:

pack :: forall a . Show a => a -> Showable 
    pack x = Showable x 

但是,似乎不可能创建将解包来自Showable的数据的反函数。如果我尝试只是颠倒了我写了包,并写:

unpack :: exists a . Show a => Showable -> a 
    unpack (Showable x) = x 

然后我从GHC的错误。

我已经查看了关于GHC语言扩展的文档,似乎没有对exists关键字的支持。我已经看到在其他一些Haskell编译器中可能会有这种可能,但我更希望能够在GHC中做到这一点。

有趣的是,我仍然可以在Showable上模式匹配,并以这种方式从内部提取数据。所以我可以通过这种方式获得价值,但是如果我想制作一个涉及Showable的免提功能,那么我需要解包。

那么有没有什么办法可以在GHC的Haskell中实现解压缩,也许使用Type家族或者其他一些GHC扩展的神秘魔法?

+0

会是什么'(解包(包(1 ::智力)))::字符串“是吗? – Cirdec

+0

我认为这应该是一个编译错误,因为你打算在打包这个值之后给它一个类型,因为在你打包之后你会丢失关于内部错误的信息,所以你不知道你是否可以将其类型更改为String。 –

回答

4

您输入的unpack不能写入。原因在于存在变量a“逃避”模式匹配的范围,并且没有设施来跟踪该行为。报价文档:

data Baz = forall a. Eq a => Baz1 a a 
     | forall b. Show b => Baz2 b (b -> b) 

当模式匹配,每个图案匹配引入了一个新的,不同的,类型为每个存在的类型的变量。这些类型不能与任何其他类型统一,也不能脱离模式匹配的范围。例如,这些碎片不正确:

f1 (MkFoo a f) = a 

结果类型中的这个“a”是什么?显然我们不是这个意思:

f1 :: forall a. Foo -> a -- Wrong! 

原来的程序只是错误的。下面是另一个类型的错误

f2 (Baz1 a b) (Baz1 p q) = a==q 

这是确定的说a==bp==q,但a==q是错误的,因为它相当于从两个Baz1构造所产生的两种截然不同的。

但是,您可以重写unpack类型等价,这样的生存确实不逃生

{-# LANGUAGE ExistentialQuantification #-} 
{-# LANGUAGE RankNTypes    #-} 

module Lib where 

data Showable = forall a. Show a => Showable a 

pack :: Show a => a -> Showable 
pack = Showable 

unpack :: Showable -> (forall a. Show a => a -> r) -> r 
unpack (Showable a) a2r = a2r a 
相关问题