2017-11-18 15 views
3

私は演算子を定義する方法について知りたいと思います。演算子がすでにMaybeでないものがであるHaskellに既に存在し、何も返されない場合は、デフォルト。基本的にはこのような何か:多分合体演算子

let x = a ?? b ?? c ?? 1 

(??)は演算子であり、a, b, cはすべてMaybeタイプです。 a, b, cがすべてNothingの場合、このコードでは最初の値がJustまたは1であると期待しています。

私は基本的に、C#や他の言語で見つかるヌル合体演算子と同じ機能を再現しようとしています。

この質問は、 F#(Null Coalescing Operator in F#?)でそれを行う方法を示しており、かなりハッキーです。ハスケルでそれをきちんとやり遂げる方法はありますか?もしそうでなければ、あなたはそれに最も近づくことができますか?

+2

[Hoogle(https://www.haskell.org/hoogle/?hoogle=Maybe+a+-%3E+Maybe+a+-%3E+Maybe+a)がこれを見つけるための優れたツールでありますものの種類。 – AJFarmar

答えて

11

Haskellerのは、一般的にこの種のもののために(<|>) :: Maybe a -> Maybe a -> Maybe aを使用します。 a, b, c :: Maybe Intと仮定すると、あなたはもちろんx :: Maybe Int

let x = a <|> b <|> c <|> Just 1 

持っている、それはあなたが求めて本当にではありません。あなたが望むなら、それを定義することもできます!

-- You expect `a ?? b ?? c ?? 1` to parse as `a ?? (b ?? (c ?? 1))` 
infixr 3 ?? 

-- (Someone is going to point out that `(??) = flip fromMaybe`, so I am first) 
(??) :: Maybe a -> a -> a 
Just x ?? _ = x 
Nothing ?? y = y 

次に、期待する動作を正確に取得します。 a, b, c :: Maybe Intと仮定すると、あなたはx :: Intをしている:ちょうどいくつかの練習のためにこの仕事はまた、左端の非何も値を返すMaybeモノイドであるMonoidクラス型Firstで表現することができる

let x = a ?? b ?? c ?? 1 
+0

あなたの答えはより良いです。 – HuStmpHrrr

+0

便利な 'インスタンスNum a => Num(Maybe a)'があれば '<|>'と '1'を使うことができます。 –

+0

'Data.Foldable'の' asum'を使って '<|>'を使ってmaybesのリストを結合することもできます。 – danidiaz

3

どうやって書きますか?

safeHead [] d = d 
safeHead (h:_) _ = h 

その後、

let x = safeHead (catMaybes [a, b, c]) 1 

はあなたがやりたいもの。

このようにしたい場合は実行可能ですが、2つの演算子が必要です。

[email protected](Just _) ?? _ = a 
_ ?? b = b 

(Just e) ?: _ = e 
_ ?: d = d 

はあなたが必要な2つの演算子を定義し、彼らは働く:

Prelude> let a = Nothing 
Prelude> let b = Nothing 
Prelude> let c = Just 3 
Prelude> a ?? b ?? c ?: 10 
3 
Prelude> a ?? b ?? Nothing ?: 10 
10 
+0

これはうまくいきますが、上記の方法で具体的に実行してほしいということを明確にする必要があると思います。私はそれを編集し、F#で見た例を追加します。 – m0meni

+0

@ m0meni私はF#をプログラムしていません。申し訳ありません。しかし、私はあなたにhaskellの演算子(しかし2つの演算子)を使ってそれを行う方法を示すことができます。 – HuStmpHrrr

1

import Data.Monoid 
import Data.Maybe (fromJust) 

infixr 3 ?? 

(??) :: Maybe a -> a -> a 
x ?? y = fromJust . getFirst $ First x <> First (Just y) 

*Main> Nothing ?? Nothing ?? 1 
1 
*Main> Nothing ?? Just 3 ?? 1 
3 
*Main> Just 7 ?? Just 3 ?? 1 
7