在Haskell case语句中省略构造函数参数

时间:2014-03-20 15:35:17

标签: haskell

省略函数参数是简洁的Haskell代码的一个很好的工具。

h :: String -> Int
h = (4 +) . length

如何在case语句中省略数据构造函数参数。以下代码可能被认为有点蹩脚,其中siAB中的最后一个参数,但是作为每个代码的最终参数重复案例匹配。

f :: Foo -> Int
f = \case
     A s -> 4 + length s
     B i -> 2 + id i

在案例模式匹配中有没有办法省略这些参数?对于具有大量参数的构造函数,这将从根本上缩短代码宽度。例如。以下伪代码。

g :: Foo -> Int
g = \case
     {- match `A` constructor -> function application to A's arguments -}
     A -> (4 +) . length
     {- match `B` constructor -> function application to B's arguments -}
     B -> (2 +) . id

2 个答案:

答案 0 :(得分:7)

GHC扩展RecordWildCards允许您简明地将构造函数的所有字段纳入范围(当然,这需要您为这些字段指定名称)。

{-# LANGUAGE LambdaCase, RecordWildCards #-}

data Foo = Foo {field1, field2 :: Int} | Bar {field1 :: Int}

baz = \case
    Foo{..} -> 4 + field2
    Bar{..} -> 2 + field1

-- plus it also "sucks in" fields from a scope
mkBar400 = let field1 = 400 in Bar{..}

`

答案 1 :(得分:1)

您始终可以将构造函数上的case语句重构为单个函数,以便从那时起只将简洁的函数定义作为参数传递给这些特定函数。请允许我举例说明。

考虑Maybe a数据类型:

 data Maybe a = Nothing | Just a

您现在是否需要定义一个函数f :: Maybe a -> b(对于某些固定的b,也许还有a),而不是像

那样编写它
 f Nothing = this
 f (Just x) = that x

你可以先定义一个函数

 maybe f _ Nothing = f
 maybe _ g (Just x) = g x

然后f可以定义为maybe this that。就像所有熟悉的递归模式一样。

通过这种方式,您可以有效地重构案例陈述。代码变得更加清晰,并且不需要语言扩展。