4

私が与えられた問題はこう言っています:

mapMaybe と同様の方法で、次の関数を定義します: composeMaybe :: (a->Maybe b) -> (b -> Maybe c) -> (a-> Maybe c) は、2 つのエラーを発生させる関数を構成します。

型 Maybe a と関数 mapMaybe は次のようにコーディングされます。

data Maybe a = Nothing | Just a

mapMaybe g Nothing = Nothing
mapMaybe g (Just x) = Just (g x)

私はこのような構成を使用してみました:

composeMaybe f g = f.g

しかし、それはコンパイルされません。

誰かが私を正しい方向に向けることができますか?

4

6 に答える 6

7

お探しのツールは既に存在します。Control.Monadには2つのKleisli合成演算子があります。

(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c
(<=<) :: Monad m => (b -> m c) -> (a -> m b) -> a -> m c

m = Maybeの場合、composeMaybeの実装が明らかになります。

composeMaybe = (>=>)

の定義を見て(>=>)

f >=> g     = \x -> f x >>= g

自分の言葉で考えたい場合は、インライン化できます。

composeMaybe f g x = f x >>= g

doまたは、 -sugarで次のように書くことができます。

composeMaybe f g x = do 
    y <- f x
    g y

一般的に、私は(>=>)、モナドの法則を述べる最もクリーンな方法を提供するので、存在するための素晴らしい理論的理由がある、を使用することに固執します。

于 2010-01-14T19:51:03.970 に答える
6

まず第一に、f と同じ引数を取り、g と同じ戻り値を返す関数が必要なためg.fではありません。f.gただし、f の戻り値の型が g の引数の型と等しくないため、これは機能しません (f の戻り値の型には Maybe があり、g の引数の型にはありません)。

したがって、あなたがする必要があるのは:Maybe b引数として a を取る関数を定義します。その引数がNothingの場合、 を返す必要がありNothingます。引数が の場合、Just bを返す必要がありg bます。composeMaybef を使用して関数の構成を返す必要があります。

于 2010-01-14T14:30:53.403 に答える
5

これはHaskell モナド (特に、最初の例で使用されているMaybe モナド) に関する優れたチュートリアルです。

于 2010-01-14T14:34:53.763 に答える
4
composeMaybe :: (a -> Maybe b)
             -> (b -> Maybe c)
             -> (a -> Maybe c)
composeMaybe f g = \x ->

gは type の引数を取りますが、 typebf値を生成するため、その結果を に渡したい場合Maybe bは、 の結果でパターン マッチを行う必要があります。f xg

                         case f x of
                              Nothing -> ...
                              Just y  -> ...
于 2010-01-14T14:36:51.483 に答える
3

非常によく似た関数がすでに存在します — モナド バインド演算子>>=. その型 (Maybe モナドの場合) はMaybe a -> (a -> Maybe b) -> Maybe bであり、次のように使用されます。

Just 100 >>= \n -> Just (show n) -- gives Just "100"

composeMaybeこれは、最初の引数に直接の Maybe 値の代わりに Maybe を返す関数を受け取る関数とまったく同じではありません。しかし、この演算子を使用して関数を非常に簡単に書くことができますcomposeMaybe— 通常の構成関数の定義と同じくらい簡単(.) f g x = f (g x)です。

于 2010-01-14T19:40:32.273 に答える
0

composeMaybeの引数の型が、モナド バインド演算子が後者の引数に必要とするものにどれほど近いかに注意してください。

ghci> :t (>>=)
(>>=) :: (Monad m) => m a -> (a -> m b) -> m b

fとの順番gが逆なので、もっといい名前はいかがですか?

thenMaybe :: (a -> Maybe b) -> (b -> Maybe c) -> (a -> Maybe c) 
thenMaybe f g = (>>= g) . (>>= f) . return

次の定義が与えられた場合

times3 x = Just $ x * 3

saferecip x
  | x == 0 = Nothing
  | otherwise = Just $ 1 / x

たとえば、

ghci> saferecip `thenMaybe` times3 $ 4
Just 0.75
ghci> saferecip `thenMaybe` times3 $ 8
Just 0.375
ghci> saferecip `thenMaybe` times3 $ 0
Nothing
ghci> times3 `thenMaybe` saferecip $ 0
Nothing
ghci> times3 `thenMaybe` saferecip $ 1
Just 0.3333333333333333
于 2010-01-19T20:46:26.407 に答える