省略函数参数是简洁的Haskell代码的一个很好的工具。
h :: String -> Int
h = (4 +) . length
如何在case语句中省略数据构造函数参数。以下代码可能被认为有点蹩脚,其中s
和i
是A
和B
中的最后一个参数,但是作为每个代码的最终参数重复案例匹配。
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
答案 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
。就像所有熟悉的递归模式一样。
通过这种方式,您可以有效地重构案例陈述。代码变得更加清晰,并且不需要语言扩展。