2017-07-09 3 views
2

ハスケル(ちょうどバインド関数を学んだこと)を始めたところです。私はモナドの中で左から右の操作を連鎖させる方法が好きです。明示的にモナドに戻っていないバインド関数の代替手段

以下のコードをもっとうまく書く方法があるのでしょうか?

main = do 
    print $ Just 10 
     >>= (\x -> return (x*2)) 
     >>= (\x -> return (x*3)) 

ラムダとリターンが一部の機能が部分的に適用されているように感じられます。に、

monads.hs:8:13: 
    Couldn't match expected type `a0 -> Maybe b0' 
       with actual type `Maybe Int' 
    In the second argument of `(>>=)', namely 
     `(\ x -> return (x * 3)) ### (+ 3)' 
    In the second argument of `($)', namely 
     `Just 10 >>= (\ x -> return (x * 2)) 
     >>= (\ x -> return (x * 3)) ### (+ 3)' 
    In a stmt of a 'do' block: 
     print 
     $ Just 10 >>= (\ x -> return (x * 2)) 
     >>= (\ x -> return (x * 3)) ### (+ 3) 

monads.hs:8:14: 
    Couldn't match expected type `a1 -> m0 a1' 
       with actual type `Maybe Int' 
    The lambda expression `\ x -> return (x * 3)' has one argument, 
    but its type `Maybe Int' has none 
    In the first argument of `(###)', namely `(\ x -> return (x * 3))' 
    In the second argument of `(>>=)', namely 
     `(\ x -> return (x * 3)) ### (+ 3)' 

をとにかく、便利なツールであると考えられる:

はもちろん非ジェネリック、醜いです:)コンパイルされません
(###) :: Maybe Int -> (Int -> Int) -> Maybe Int 
(Just x) ### f = Just (f x) 
Nothing ### f = Nothing 

main = do 
    print $ Just 10 
     >>= (\x -> return (x*2)) 
     >>= (\x -> return (x*3)) 
     ### (+3) -- the result should be (Just 63) 

:私はそのような何かを考えていました中間結果(do-notation)をあまり気にせず、Nothingにフォールバックするときにコードに明示的に指示することなく、モナド内で一連の操作を連鎖させることができます。

  1. そのための組み込み関数はありますか?
  2. もしそうでない場合は、私の###機能を汎用、ダンディー、コンパイルに変更するにはどうすればよいですか?
+1

あなたの '(###)'は本質的に 'fmap'をひっくり返しています。 'fmap'の型は' Functor f =>(a - > b) - > f a - > f b'です。一度あなたが 'たぶん'に特化すれば '(a - > b) - >多分a - >多分b'になります。 [これと多少似た質問](https://stackoverflow.com/q/42674517/2751851)も参照してください。 – duplode

+1

['(<&>)'](http://hackage.haskell.org/package/lens-4.15.3/docs/Control-Lens-Lens.html#v:-60--38--62- )は '(###)'の一般化されたバージョンです。おかげさまで – Alec

答えて

4

おめでとう、あなたはFunctor秒を発明しました! MaybeためFunctor例えばsourceをチェックアウト:

instance Functor Maybe where 
    fmap _ Nothing  = Nothing 
    fmap f (Just a)  = Just (f a) 

それはm >>= return . f = fmap f mあまり言及したモナドの法則の一つである - モナドアクションとファンクタアクション間の「コヒーレンス」法の一種。

fmapも中置の別名、(<$>)を持っているので、あなたは

main = print ((+3) <$> (*2) <$> (*3) <$> Just 10) 

を書くことができ、これはJust 63を出力します。

+0

私はFunctorsと何か関係があったと感じていました:)私は、処理命令を残す権利は好きではありませんでした。 Alecのコメントに記載された '<&>'はこの問題を解決します。 – gisek