有没有办法在GHC的Haskell中表示在Showable上解压缩功能?

时间:2016-05-12 19:17:52

标签: haskell ghc exists qualifiers

我有一个名为Showable的类型:

    {-# 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中实现解包,可能使用类型系列或其他一些GHC扩展的神秘魔法?

1 个答案:

答案 0 :(得分: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