解析器组合器的类型

dav*_*k01 5 parsing haskell types

如果我有一个解析器a : Parser A和一个解析器,b : Parser B那么我可以将它组合成一个解析器a | b : Parser (Either A B).当你开始添加更多替代品并获得类似的类型时,这会有点麻烦Either A (Either B C).我可以想象将之前的类型扁平化为类似的东西Alternative A B C.是否有我可以执行的标准转换,或者我坚持为类型生成一大堆样板文件Alternative A B C ....

ram*_*ion 8

所以有趣的Either是你可以将它用作类型级cons操作符.

A `Either` (B `Either` (C `Either` (D `Either` Void))) --> [A,B,C,D]
Run Code Online (Sandbox Code Playgroud)

所以我们所需要做的就是明确这一点.你需要ghc-7.8来支持封闭的数据系列:

{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE DataKinds #-}
-- ...

type family OneOf (as :: [*]) :: * where
  OneOf '[a] = a
  OneOf (a ': as) = Either a (OneOf as)
Run Code Online (Sandbox Code Playgroud)

现在,您可以更简洁地编写类型:

aorborc :: Parser (OneOf '[A, B, C])
aorborc = a | (b | c)
Run Code Online (Sandbox Code Playgroud)

它仍然Either在引擎盖下,因此您仍然可以轻松地与所有使用的现有代码进行互操作Either,这很好.