2013-02-12 38 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