Haskell guards on lambda functions?

HaskellSyntax

Haskell Problem Overview


Is it possible to have guards on lambda functions?

For example:

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

Haskell Solutions


Solution 1 - Haskell

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"

Solution 2 - Haskell

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.

Solution 3 - Haskell

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"

Solution 4 - Haskell

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 "")

Solution 5 - Haskell

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionqrestView Question on Stackoverflow
Solution 1 - HaskellGS - Apologise to MonicaView Answer on Stackoverflow
Solution 2 - HaskellJon PurdyView Answer on Stackoverflow
Solution 3 - HaskellGreg BaconView Answer on Stackoverflow
Solution 4 - HaskellWizekView Answer on Stackoverflow
Solution 5 - HaskellhololeapView Answer on Stackoverflow