2010-02-19 39 views
15

試驗存在類型。似乎是獲得某種類型靈活性的好方法。如何解開haskell存在類型?

我在將它包裝起來後拆開存在類型時遇到了問題。我的代碼如下:

{-# 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,然後抱怨BlurbBox Alpha的類型。我如何去拆箱/拆包存在類型?

回答

14

事實上,存在類型不能解開,因爲他們的整個的一點是,期待一個存在的類型的代碼必須工作絕對以同樣的方式(在參數多態性的意義上),無論與準確鍵入存在型變量被實例化。

可以理解,更好地理解是

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

被翻譯成

type BlurbBox = forall b . (forall a . Blurb a => a -> b) -> b 

就是BlurbBox是值得的,因爲對於絕對所有的Blurbs工作的多態函數,可用於產生將該函數應用於某些(未知)街區的結果。因此,類似於你不能寫一個類型爲f :: a - > Int的函數,並且f String = 5和f Bool = 3,你不能在類型'a'一個BlurbBox。

你可能會看看TAPL關於存在類型的章節。它描述了我提供的翻譯。

+0

你有鏈接瞭解這種翻譯如何/在哪裏發生? BlurbBox(構造函數)類型爲'forall a。 Blurb a => a - > BlurbBox',但類型本身(通常)與isomorphic to ..? – nicolas 2015-12-11 13:50:41

+0

,可以幫助。 https://mail.haskell.org/pipermail/haskell-cafe/2010-May/078254.html TAPL的練習23.4.8和章節24.3也是有用的 – nicolas 2015-12-11 14:53:38

4

據我所知,你不能這樣做。存在類型的要點是隱藏一個類型,所以你可以統一訪問所有的「實例」(有點像在Java和其他面向對象的語言中動態分派子類方法)。

所以,在你的榜樣,你的「接口」爲BlurbBox,你會用它來統一適用某種方法不同BlurbBoxes,而不用擔心內部類型a是(例如,如果BlurbShow,那麼你可以有一個[BlurbBox]並打印列表中的每個元素,而不必知道列表中每個BlurbBox的確切內部類型)。

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) 
... 

*我非常推薦這一點,但如果你真的想…

{-# 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" 
+0

你能否詳細說一下你的第二個版本'Dynamic's,爲什麼*反對*? – wowofbob 2017-11-11 09:12:30