【问题标题】:Is there a way to represent the function unpack on Showable in GHC's Haskell?有没有办法在 GHC 的 Haskell 中表示 Showable 上的功能解包?
【发布时间】:2016-05-12 19:17:52
【问题描述】:

我有一个名为 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 语言扩展的文档,似乎不支持存在关键字。我已经看到它可能在其他一些 Haskell 编译器中是可能的,但我更希望能够在 GHC 中做到这一点。

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

那么有没有办法在 GHC 的 Haskell 中实现解包,可能是使用类型族或其他一些 GHC 扩展的神秘魔法?

【问题讨论】:

  • (unpack (pack (1 :: Int))) :: String 会是什么?
  • 我认为这应该是一个编译错误,因为您在打包值后尝试为其提供类型,因为打包后您会丢失有关内部内容的拼写错误的信息,所以您不知道能不能把它的类型改成String。

标签: haskell ghc exists qualifiers


【解决方案1】:

您输入的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

【讨论】:

    猜你喜欢
    • 2016-12-29
    • 1970-01-01
    • 1970-01-01
    • 2020-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多