3

私はHaskellの初心者です。そして、モナドについて学んでいます。

data Container a = Container a deriving Show

x = Container 1 :: Container Int

plusOne :: Container Int -> Container Int
plusOne (Container x) = Container (x+1)

plusOneに適用するために持ち上げる方法はありますContainer (IO Int)か?

または、次のような新しい関数を定義する必要があります。

plusOne' :: Container (IO Int) -> Container (IO Int)  
plusOne' (Container x) = Container (liftM (+1) x)

ありがとう :-) そして、 plusOne の再定義を避ける方法はありますか?

プログラムをビルドするときは、最初に非モナディック型のコンテナ (Container Int などの通常の値) を使用してプログラムをビルドし、指定された値 (Container 10..) で関数をテストします。

その後、これらのプログラムをランダムまたは生成された値に適用しようとします。これは、他の言語 (Lisp、Python など) でのプログラミングに対する私の基本的なアプローチです。

したがって、これらの関数をモナド値コンテナーに適用しようとするときに、関数を再定義したくありません。

このアプローチは Haskell プログラミングでは機能しませんか? マインドモデルを変えるべきですか?それともHaskellについて誤解していますか?

4

2 に答える 2

8

FunctorContainerのインスタンスのように見えます:

instance Functor Container where
    fmap f (Container a) = Container (f a)

それで

plusOne = fmap (+1)

plusOne' = fmap $ liftM (+1)

しかし、今、私は質問を誤解していたかもしれないと思います...

于 2013-03-29T00:43:06.500 に答える
7

まず最初に、実際にIdentityモナドを再定義したようです。

fmapここで行うように、他のファンクターを含むファンクターがある場合、適切な数のs などを取得したことを確認するために、すべての簿記を自分で行う必要はありません。そこでモナド変換子の出番です。

MTL ライブラリ(これは Haskell Platform に付属しているはずです) が面倒な作業をすべて行ってくれます。既存のすべてのモナド トランスフォーマーで独自の型が機能するようにするには、少し (OK、かなり多くの) 配管作業を行う必要があります。それができたらContainer、モナドスタックのメンバーとして良き市民になるべきです。

もちろん、通常の警告が適用されます: モナド変換子は強力で理解しにくいものです。必要だと思う半分の時間は、実際には必要ありません。そのため、最初に問題を解決するために正しいアプローチを使用していることを確認してください。

于 2013-03-29T01:23:08.330 に答える