如何解压缩haskell存在类型?

me2*_*me2 16 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 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"
Run Code Online (Sandbox Code Playgroud)

此代码编译为main,然后抱怨BlurbBox Alpha的类型.如何解除存储类型的拆箱/解包?

jkf*_*kff 16

实际上,存在类型不能被解包,因为它们的全部意义在于,期望存在类型的代码必须以完全相同的方式(在参数多态性的意义上)工作,而不管实例化存在类型变量的确切类型.

通过理解,你可以更好地理解

data BlurbBox = forall a . Blurb a => BlurbBox a
Run Code Online (Sandbox Code Playgroud)

被翻译成

type BlurbBox = forall b . (forall a . Blurb a => a -> b) -> b
Run Code Online (Sandbox Code Playgroud)

也就是说,BlurbBox是一种可以用于绝对所有Blurbs的多态函数,可用于产生将该函数应用于某些(未知)模糊的结果.

因此,类似于你不能编写f :: a - > Int类型的函数并且f string = 5和f Bool = 3,你不能在BlurbBox中调用'a'的类型.

您可以查看存在类型的TAPL章节.它描述了我提供的翻译.


eph*_*ent 11

在隐藏它之后,你不能*专门化一种类型.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)
...
Run Code Online (Sandbox Code Playgroud)

*我非常建议要这样做,但如果你真的想......

{-# 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"
Run Code Online (Sandbox Code Playgroud)