[著者からの編集、6年後]これは不必要に長い答えであり、なぜそれが受け入れられたのかわかりません。最高の賛成の答えで提案されているように、maybe
またはを使用してください。Data.Maybe.fromMaybe
以下は、実践的なアドバイスというよりも、思考実験です。
そのため、さまざまなタイプで機能する関数を作成しようとしています。これはクラスを作るのに良い時期です。JavaまたはC++でプログラミングした場合、Haskellのクラスはそれらの言語のインターフェースのようなものです。
class Nothingish a where
nada :: a
このクラスは値を定義しますnada
。これは、クラスと同等の値であると想定されていますNothing
。さて、楽しい部分です。このクラスのインスタンスを作成することです。
instance Nothingish (Maybe a) where
nada = Nothing
タイプの値の場合Maybe a
、Nothing-like値は、まあ、Nothing
!これはすぐに奇妙な例になります。しかしその前に、リストをこのクラスのインスタンスにもしましょう。
instance Nothingish [a] where
nada = []
空のリストは、何もないようなものですよね?したがって、文字列(Charのリスト)の場合、空の文字列を返します""
。
数字も簡単に実装できます。あなたはすでに、0が数字の「無」を表すことを明らかに示しました。
instance (Num a) => Nothingish a where
nada = 0
これは、ファイルの先頭に特別な行を配置しない限り、実際には機能しません。
{-# LANGUAGE FlexibleInstances, UndecidableInstances, OverlappingInstances #-}
または、コンパイル時に、これらの言語プラグマのフラグを設定できます。それらについて心配する必要はありません。それらは、より多くのものを機能させる魔法にすぎません。
これで、このクラスとそのインスタンスができました...関数を書き直してそれらを使用しましょう!
eliminate :: (Nothingish a) => Maybe a -> a
eliminate (Just a) = a
eliminate Nothing = nada
に変更0
しただけnada
で、残りは同じであることに注意してください。試してみましょう!
ghci> eliminate (Just 2)
2
ghci> eliminate (Just "foo")
"foo"
ghci> eliminate (Just (Just 3))
Just 3
ghci> eliminate (Just Nothing)
Nothing
ghci> :t eliminate
eliminate :: (Nothingish t) => Maybe t -> t
ghci> eliminate Nothing
error! blah blah blah...**Ambiguous type variable**
価値観などに最適です。(Just Nothing)がNothingに変わることに注意してください。それは奇妙な例でした、多分多分。とにかく...どうeliminate Nothing
ですか?さて、結果のタイプはあいまいです。私たちが何を期待しているのかわかりません。したがって、必要なタイプを指定する必要があります。
ghci> eliminate Nothing :: Int
0
先に進んで、他のタイプで試してみてください。あなたはそれがnada
それぞれのために得るのを見るでしょう。したがって、この関数を関数で使用すると、次のcombine
ようになります。
ghci> let combine a b c = (eliminate a, eliminate b, eliminate c)
ghci> combine (Just 2) (Just "foo") (Just (Just 3))
(2,"foo",Just 3)
ghci> combine (Just 2) Nothing (Just 4)
error! blah blah Ambiguous Type blah blah
「Nothing」のタイプを指定するか、期待するリターンタイプを指定する必要があることに注意してください。
ghci> combine (Just 2) (Nothing :: Maybe Int) (Just 4)
(2,0,4)
ghci> combine (Just 2) Nothing (Just 4) :: (Int, Int, Int)
(2,0,4)
または、型シグネチャをソースに明示的に配置することで、関数が許可する型を制限することもできます。これは、関数の論理的な使用法が、同じタイプのパラメーターでのみ使用される場合に意味があります。
combine :: (Nothingish a) => Maybe a -> Maybe a -> Maybe a -> (a,a,a)
combine a b c = (eliminate a, eliminate b, eliminate c)
今では、3つすべてが同じタイプである場合にのみ機能します。そうすれば、Nothing
は他のタイプと同じタイプであると推測されます。
ghci> combine (Just 2) Nothing (Just 4)
(2,0,4)
あいまいさはありません、イェーイ!しかし、今では、以前と同じように、組み合わせるのはエラーです。
ghci> combine (Just 2) (Just "foo") (Just (Just 3))
error! blah blah Couldn't match expected type blah blah
blah blah blah against inferred type blah blah
まあ、それは十分に長くて誇張された答えだったと思います。楽しみ。