如何解包haskell存在类型?

如何解包haskell存在类型?,haskell,types,Haskell,Types,实验存在类型。这似乎是获得某种类型灵活性的好方法 我遇到了一个问题,在我结束一个存在主义类型之后,我将它拆开。我的代码如下: {-# LANGUAGE ExistentialQuantification #-} class Eq a => Blurb a data BlurbBox = forall a . Blurb a => BlurbBox a data Greek = Alpha | Beta deriving Eq instance Blurb Greek data

实验存在类型。这似乎是获得某种类型灵活性的好方法

我遇到了一个问题,在我结束一个存在主义类型之后,我将它拆开。我的代码如下:

{-# LANGUAGE ExistentialQuantification #-}

class Eq a => Blurb a
data BlurbBox = forall a . Blurb a => BlurbBox a

data Greek = Alpha | Beta deriving Eq
instance Blurb Greek

data English = Ay | Bee deriving Eq
instance Blurb English

box1 :: BlurbBox
box1 = BlurbBox Alpha

box2 :: BlurbBox
box2 = BlurbBox Ay

main = do
    case box1 of
        BlurbBox Alpha -> putStrLn "Alpha"
        BlurbBox Beta -> putStrLn "Beta"
        BlurbBox Ay -> putStrLn "Ay"
        BlurbBox Bee -> putStrLn "Bee"

这段代码编译到main,然后抱怨blurbboxalpha的类型。我如何去拆开/拆开一个存在类型?

据我所知,你不能这么做。存在类型的全部要点是隐藏一个类型,这样您就可以统一地访问所有“实例”(有点像Java和其他面向对象语言中动态分派子类方法)


因此,在您的示例中,您的“接口”是
BlurbBox
,您可以使用它将某些方法统一应用于不同的BlurbBox,而不必担心内部类型
a
是什么(例如,如果
Blurb
子类
Show
,则您可以拥有
[BlurbBox]
并打印列表中的每个元素,而无需知道列表中每个
BlurbBox
的确切内部类型)。

隐藏类型后,无法*专门化类型。如果您需要这样的操作,请向
Blurb
添加一些约束或方法

-- choose one
class (Eq a, Show a) => Blurb a where
    printBlurb :: a -> IO ()
instance Blurb Greek where
    printBlurb Alpha = putStrLn "Alpha"
...

class (Eq a, Show a) => Blurb a
data Greek deriving (Eq, Show)
...

data BlurbBox = forall a. (Blurb a, Show a) => BlurbBox a
data Greek deriving (Eq, Show)
...

*我非常反对这个,但是如果你真的想

{-# LANGUAGE DeriveDataTypeable #-}
import Data.Dynamic

data Greek = Alpha | Beta deriving (Eq, Typeable)
data English = Ay | Bee deriving (Eq, Typeable)

box1 :: Dynamic
box1 = toDyn Alpha

box2 :: Dynamic
box2 = toDyn Ay

main = do
    case fromDynamic box1 of
      Just Alpha -> putStrLn "Alpha"
      Just Beta -> putStrLn "Beta"
      Nothing -> case fromDynamic box1 of
        Just Ay -> putStrLn "Ay"
        Just Bee -> putStrLn "Bee"

事实上,存在类型是无法解包的,因为它们的全部要点是,期望存在类型的代码必须以完全相同的方式工作(在参数多态性的意义上),而不管存在类型变量是用哪种类型实例化的

你可以更好地理解这一点

data BlurbBox = forall a . Blurb a => BlurbBox a
被翻译成

type BlurbBox = forall b . (forall a . Blurb a => a -> b) -> b
也就是说,BlurbBox是这样一种东西,给定一个适用于所有模糊的多态函数,它可以用于生成将该函数应用于某些(未知)模糊的结果

因此,与不能编写类型为f::a->Int且f String=5和f Bool=3的函数类似,不能在BlurbBox中分派类型为“a”的函数


你可以看看《存在类型》中的一章。它描述了我提供的翻译。

您是否有关于如何/在何处进行翻译的链接?BlurbBox(构造函数)的类型为所有a。Blurb a=>a->BlurbBox但类型本身(通常)与..同构?那会有帮助的。TAPL的练习23.4.8和第24.3章很有用,请您详细介绍一下您的第二个版本,使用
Dynamic
s,为什么反对?