在Haskell中的case语句中使用默认值

时间:2013-02-12 23:09:01

标签: haskell

我正在尝试创建一个名为place的新数据声明。

看起来像这样:

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

我希望然后使用一个名为cap的函数来取代它的资本:

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,我没有得到未定义的响应。相反,我得到一个不在范围内的错误。有人可以帮助我解决我的困惑,也许可以提供一种试图捕捉其他案件的合法方式吗?

3 个答案:

答案 0 :(得分:9)

问题不在于你如何处理丢失的案件 - 你如何处理它是好的。问题是Wales构造函数根本不存在。因此,就像当您尝试使用尚未定义的变量或函数时,您会收到编译错误。您的cap函数甚至从未被调用过,因此您无法对其进行任何更改会影响此行为。使用不存在的构造函数编译代码是无法做到的。

答案 1 :(得分:4)

当您输入capital Wales时,范围内没有Wales。您无法构造不存在的值。如果您已涵盖所有可能的案例,那么您不需要默认案例。

答案 2 :(得分:3)

对sepp2k和singpolyma的答案进行重复,这里的重点是Haskell的联合类型详尽。当您使用 n 情况定义联合类型时,您告诉Haskell那些 n 情况是您的类型唯一存在的情况。正如singpolyma指出的那样,你告诉Haskell其他案例甚至不存在。

这有利有弊。穷举意味着您和编译器可以保证您的函数正在处理它们将被给予的所有可能输入。缺点是在编译时修复了一组案例。

这里最简单的选择是两部分:

  1. 使用“开放”类型 - 您可以在运行时创建任意多个不同的实例 - 来表示国家和大写字母。弦乐在这里很好;您可以在运行时构建无限数量的不同字符串。但您也可以使用带有字符串成员的记录类型。
  2. 使用键/值分配数据结构来表示国家与首都之间的关联。
  3. 所以你可以像这样代表国家和城市:

    -- 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)查找时间。更好的方法是使用Haskell平台附带的Data.Map