2013-02-12 47 views
4

我試圖創建一個名爲place的新數據聲明。在Haskell的case語句中使用默認值

它看起來像這樣:

data place = United States | France | England | Germany | Mexico | Canada

我的希望是,然後使用一個名爲帽功能採取的地方,它的資本,像這樣:

cap :: place -> String 
cap a = case a of 

      Spain   -> "Madrid" 
      France   -> "Paris" 
      England   -> "London" 
      Germany   -> "Berlin" 
      Mexico   -> "Mexico City" 
      Canada   -> "Ottawa" 
      _    -> undefined 

但是最後的情況下,我試圖捕獲數據聲明中可能不存在的所有其他條目不起作用。例如,如果我在GHCI中輸入capital Wales,我不會收到未定義的答覆。相反,我得到一個不在範圍內的錯誤。有人可以幫我解決我的困惑,也許可以提供一種嘗試捕捉其他情況的合法方式嗎?

+0

暫時將另一個國家添加到您的代碼中'data Place = Temp |美國| ...'那麼你可以測試'帽子溫度'。 – AndrewC 2013-02-12 23:19:59

+2

(您的數據聲明現在已被打破,應該說'data Place = UnitedStates | France | England | Germany | Mexico | Canada'。) – AndrewC 2013-02-12 23:22:15

回答

9

問題不在於你如何處理遺失的情況 - 你如何處理它是好的。問題是Wales構造函數根本不存在。所以就像當你嘗試使用一個未定義的變量或函數時,你會得到一個編譯錯誤。你的cap函數甚至不會被調用,所以你可以做的任何改變都不會影響這種行爲。沒有什麼可以做使用不存在的構造函數編譯的代碼。

4

當您輸入capital Wales時,範圍內沒有Wales。你不可能構建一個不存在的值。如果您已經涵蓋了所有可能的案例,那麼您不需要默認案例。

+0

這很有道理。如果用戶不知道只有這些國家在聲明中,那麼真的沒有辦法提供默認的「捕捉」聲明嗎? – ZAX 2013-02-12 23:11:51

+0

@ZAX您的語法對於默認情況是正確的,但無法傳入觸發該情況的值。編譯器將首先捕獲錯誤:) – singpolyma 2013-02-12 23:12:49

3

要對sepp2k和singpolyma的答案進行細化,這裏的要點是Haskell的聯合類型是窮舉。當您使用n個案定義工會類型時,您告訴Haskell這些案件是您的類型唯一存在的案件。正如singpolyma指出的那樣,你告訴Haskell其他案例甚至不存在

這有好處和缺點。徹底性意味着你和編譯器可以保證你的函數處理所有可能的輸入。缺點是這些案例在編譯時是固定的。

這裏最簡單的方法是由兩部分組成:

  1. 使用「開放」的類型之一,你可以在運行時創建任意多個不同的情況下,代表國家和首都。絃樂在這裏是一個很好的例子。可以在運行時構建無數不同的字符串。但是你也可以使用帶有字符串成員的記錄類型。
  2. 使用鍵/值分配數據結構來表示國家和首都之間的關聯。

所以,你可以代表國家和城市是這樣的:

-- Since there are infinitely many different strings you could construct at runtime, 
-- there are also infinitely many different Cities and Nations... 
data City = City String deriving (Eq, Ord, Show) 
data Nation = Nation String deriving (Eq, Ord, Show 

最簡單的鍵/值映射類型是[(k, v)],常常被稱爲關聯列表。它當然有一個O(n)查找時間。更好的方法是使用Data.Map,它隨Haskell平臺一起提供。

+2

或者他可以爲他的聯盟添加一個「其他字符串」的術語作爲後備。 – 2013-02-13 02:36:55