尝试存在类型.似乎是获得某种类型灵活性的好方法.
在我把它包起来之后,我遇到了一个解除存储类型的问题.我的代码如下:
{-# 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)