web-dev-qa-db-ja.com

Haskellはラムダ関数をガードしますか?

ラムダ関数にガードを付けることは可能ですか?

例えば:

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

他の回答は、この回答が最初に書かれてから導入された拡張機能LambdaCaseおよびMultiWayIfがこれをどのように解決できるかを示しています。それらがなければ、最も近い直接翻訳は少し似ています

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

GHC 7.6.1 以降では、MultiWayIfという拡張機能があり、次のように記述できます。

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

少なくとも、caseを使用する代替方法よりも、どちらを見るのが楽しいでしょう。

パターンマッチングには、LambdaCaseと呼ばれる関連する拡張機能があります。

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

ただし、これらの拡張機能は標準のHaskellの一部ではないため、ファイルの上部にある{-# LANGUAGE LambdaCase #-}または{-# LANGUAGE MultiWayIf #-}プラグマを介して明示的に有効にするか、フラグ-XLambdaCaseを使用してコンパイルするか、 -XMultiWayIf

47
Jon Purdy

読者の視覚的な流れを壊さないように、ラムダを短くて甘く保つのが好きです。定義が構文的にかさばり、ガードを保証するのに十分な関数の場合、それをwhere句に貼り付けてみませんか?

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

LambdaCaseでそれを行うためのエレガントで簡潔な方法:

{-# LANGUAGE LambdaCase #-}
\case k | k < 0     -> "negative"
        | k == 0    -> "zero"
        | otherwise -> "positive"

または

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

EOFエラーをキャッチするために使用した場合:

{-# LANGUAGE ScopedTypeVariables #-}
o <- hGetContents e `catch` (\case (e :: IOException) | isEOFError e -> return "")
7
Wizek

さらに別の方法では、LambdaCaseViewPatternsGHC拡張機能の組み合わせを使用します。

{-# LANGUAGE LambdaCase, ViewPatterns #-}

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

これにより、中間変数に名前を付ける必要がなくなります。

1
hololeap