2017-01-21 19 views
1

我很確定我的問題源於我是Haskell的新手,並不完全理解類型系統。「SubTypes」與自己的顯示和其他模塊中可用

我將使用Haskell的維基用在

以下類型定義

data Suit = Club | Diamond | Heart | Spade 

現在第一個問題是主題類型的例子,我想實現Show每一個「子鍵入「(俱樂部,鑽石,心臟,黑桃),但這似乎不工作,因爲它是一個DataKinds。所以我把它分成他們自己的類型。 (屬性沒有太大的意義,但我說他們是更接近真實的代碼)

data ClubType = ClubType { 
    clubName :: String, 
    icon :: String 
} 
instance Show ClubType where 
    show (ClubType cn i) = "name: " ++ cn ++ ", icon: " ++ i 

在西裝式

data Suit = Club ClubType 
      | Diamond DiamondType 
      | Heart HeartType 
      | Spade SpadeType 

現在我想用衣服和使用它們「子類型「(俱樂部,鑽石,心臟,黑桃)在不同的module。我只出口了Suit (..)

使用

import Module1 (Suit(..)) 

getSuit :: String -> Suit 
getSuit "Club" = getClub 
getSuit "Heart" = getHeart 
... 

getClub ::() -> Club 

現在再次ClubHeartDiamondSpade不能使用,因爲它們DataKinds。我如何使用「子類型」?我是否需要導出所有類型?如果我這樣做,是否符合getSuit的退貨類型?

(很抱歉,如果該示例沒有一大堆的道理,但我希望你能按照我需要的結果)

感謝

回答

5

是的,它聽起來像你真的不明白的類型系統。我會盡我所能來澄清我認爲你會出錯的地方。在你的例子中

data Suit = Club | Diamond | Heart | Spade 

只有一種類型,那就是SuitClub,Diamond等根本不是類型,如果您將它們稱爲「子類型」,則會迷惑自己。對他們來說,正確的名稱是構造,他們基本上是值類型爲Suit

Club :: Suit 
Diamond :: Suit 
... 

所以你不能真正實現Show實例「每一個」,則只能實現一個Show實例爲整體型Suit,以通常的方式,由圖案上的構造相匹配:

instance Show Suit where 
    show Club = "Clubs" 
    show Diamond = "Diamonds" 
    show Heart = "Heart" 
    show Spade = "Spade" 

這定義的類型Suit -> String單一功能show,再次沒有「子類型「任何事情都在繼續。我想知道這是不是你想要的。

既然你提到datakinds,使用類型級別的構造函數仍然不會使它們成爲類型 - 它們仍然是Suit類型的值。利用它們在類型級別的一個例子是指數GADT這些:

data Card :: Suit -> * where 
    QueenOfSpades :: Card Spade 
    OtherCard :: Int -> Card s -- we'd want to encode the suit s at the data 
           -- level too using a singleton, out of scope 
           -- for this post 

但是,這是相當先進的東西,也許你正在尋找沒有什麼。

我希望這能澄清一點。

+0

我正要問爲什麼答案如此之短。 :)抱着我的馬! – Alec

+0

感謝您的好評。我能否以任何方式引用*構造函數?是否可以定義一個返回「Club」的函數,或者我應該只是使用'Suit'到處? – KenavR

+0

你不能談論類型級別的構造函數(除非像我在GADT例子中展示的那樣,但我不會擔心,直到你更有經驗),只需使用'Suit'。 – luqui