Haskell / GHC:匹配具有相同模式的多个一元构造函数

时间:2011-08-20 13:15:29

标签: haskell constructor pattern-matching ghc

所以我正在玩定义TrieSet数据类型(即使我知道I don't need to):

module Temp where

import Data.Map

data TrieSet a = Nonterminal (Data.Map a (TrieSet a)) | Terminal (Data.Map a (TrieSet a))

insert :: Ord a => [a] -> TrieSet a -> TrieSet a
insert [] (_ m) = Terminal m
insert (a:as) (c m) = c $ insertWith (insert as . flip const) a (insert as $ Nonterminal empty) m

当我收到一个我从未见过的错误时:

% ghc -c Temp.hs
Temp.hs:8:11: Parse error in pattern

因此,GHC似乎不喜欢使用相同模式匹配多个一元构造函数。 我做了另一个测试,以确保问题出现:

module Temp2 where

extract :: Either String String -> String
extract (_ s) = s

这似乎证实了我的怀疑:

% ghc -c Temp2.hs
Temp2.hs:4:9: Parse error in pattern

所以我的问题是(分多部分):

  1. 我对GHC不喜欢这些功能的原因是肯定的吗?
  2. 为什么这不是Haskell标准的一部分?毕竟,我们可以使用相同的模式匹配多个nullary构造函数。
  3. 是否有一个LANGUAGE编译指示我可以给GHC让它接受这些吗?

2 个答案:

答案 0 :(得分:9)

  1. 是。那种通配符从未受到支持。
  2. 在我看来,如果你不知道匹配的数据构造函数,推断一个函数的类型要困难得多。试想一下函数f (_ n) = n。应该是什么类型的? Haskell的类型系统无法描述类型构造函数的arity,因此像f这样的函数不可能存在。
  3. 我不这么认为。

答案 1 :(得分:8)

如果将两个或多个构造函数与通配符模式匹配是有意义的,那么统一这些构造函数并使用额外的枚举值来区分它们可能也是有意义的。

例如:

data Terminality = Terminal | Nonterminal
data TrieSet a = Node Terminality (Data.Map a (TrieSet a))

foo :: TrieSet X -> X
foo (Node _ m) = ...

如果您不想对现有数据类型进行此更改,则可以改为定义帮助程序类型和相应的帮助程序函数,并在模式匹配之前执行转换。

data TreeSetView a = Node Terminality (Data.Map a (TrieSet a))

view :: TrieSet a => TreeSetView a
view (Terminal    m) = TreeSetView TerminalityTerminal    m
view (Nonterminal m) = TreeSetView TerminalityNonterminal m
相关问题