qrest
qrest

Reputation: 3083

Haskell guards on lambda functions?

Is it possible to have guards on lambda functions?

For example:

\k
    | k < 0     -> "negative"
    | k == 0    -> "zero"
    | otherwise -> "positive"

Upvotes: 55

Views: 25175

Answers (5)

Ganesh Sittampalam
Ganesh Sittampalam

Reputation: 29110

Other answers show how the extensions LambdaCase and MultiWayIf, introduced since this answer was first written, can solve this. Without them, the nearest direct translation is something a bit like

\k -> case () of
       _ | k < 0     -> "negative"
         | k == 0    -> "zero"
         | otherwise -> "positive"

Upvotes: 62

hololeap
hololeap

Reputation: 1176

Yet another way uses a combination of the LambdaCase and ViewPatterns GHC extensions:

{-# LANGUAGE LambdaCase, ViewPatterns #-}

\case
    ((< 0) -> True) -> "negative"
    ((==0) -> True) -> "zero"
    _               -> "positive"

This keeps you from having to name an intermediate variable.

Upvotes: 2

Wizek
Wizek

Reputation: 4993

An elegant and concise way to do it with LambdaCase:

{-# LANGUAGE LambdaCase #-}

\case k | k < 0     -> "negative"
        | k == 0    -> "zero"
        | otherwise -> "positive"

or

\case
  k | k < 0     -> "negative"
    | k == 0    -> "zero"
    | otherwise -> "positive"

A case when I used it, to catch an EOF error:

{-# LANGUAGE ScopedTypeVariables #-}

o <- hGetContents e `catch` (\case (e :: IOException) | isEOFError e -> return "")

Upvotes: 8

Jon Purdy
Jon Purdy

Reputation: 55049

As of GHC 7.6.1 there is an extension called MultiWayIf that lets you write the following:

\k -> if
  | k < 0     -> "negative"
  | k == 0    -> "zero"
  | otherwise -> "positive"

Which at the very least is more pleasant to look at than the alternative using case.

For pattern-matching, there is a related extension called LambdaCase:

\case
  "negative" -> -1
  "zero"     -> 0
  "positive" -> 1
  _          -> error "invalid sign"

These extensions are not part of standard Haskell, though, and need to be enabled explicitly via a {-# LANGUAGE LambdaCase #-} or {-# LANGUAGE MultiWayIf #-} pragma at the top of the file, or by compiling with the flag -XLambdaCase or -XMultiWayIf.

Upvotes: 53

Greg Bacon
Greg Bacon

Reputation: 139621

I like to keep lambdas short and sweet so as not to break the reader's visual flow. For a function whose definition is syntactically bulky enough to warrant guards, why not stick it in a where clause?

showSign k = mysign ++ " (" ++ show k ++ ")"
  where
  mysign
    | k < 0     = "negative"
    | k == 0    = "zero"
    | otherwise = "positive"

Upvotes: 30

Related Questions