4

だから私は、関数は次のようにモナド演算子と関数で表現できることを発見fmapしましFunctorた:>>=return

fmap' :: (Monad m) => (a -> b) -> m a -> m b
fmap' g x = x >>= (\y ->
                return (g y))

だから私の最初の質問は、に基づいて return 関数を実装するにはどうすればよいfmapですか?

また、return 関数を に基づいて実装できればfmap、do ブロック内の Haskell 式を減らすことはできますか? それはよりエレガントなコードを生成しますか?

例えば:

Just x -> do 
    y <- f x
    return (a:y)
4

2 に答える 2

3

returnに関しては、一般的に実装できませんfmapMonadよりも強力ですFunctor

ただし、演​​習として、次の質問をしてみることができます: 2 番目の操作があれば、次returnの順番で実装できるようになりfmapますか? 型を見ることで、この問題に取り組むことができます。(代わりに from クラスをpure使用します—それらは基本的に同じ操作です。)Applicativereturn

fmap :: Functor f => (a -> b) -> f a -> f b
pure :: Applicative f => a -> f a

さて、これが進む可能性のある方法の1つは、次の関数がある場合です。

-- This is like the standard `const` function, but restricted to the `()` type:
const' :: a -> () -> a
const' a = \() -> a

次に、これを書くことができます。これは「ほぼ」pure/returnです。

almostThere :: Functor f => a -> f () -> f a
almostThere a = fmap (const' a)

そして、次のクラスがあれば、pureそれに関して書くことができます:

class Functor f => Pointed f where
    unit :: f ()

pure :: Pointed f => a -> f a
pure a = almostThere a unit

長い話を短くすると、これはつまりreturnpureをゼロからunit作成できる関数であり、既に別のを持っている場合にのみを作成できる関数です。/ をゼロから作成する「力」を持つ 3 番目の操作にアクセスできない限り、/を実装するために使用できる方法はありません。私が示した操作は、おそらくこの「力」を持つ最も単純な操作です。ffmapffmapreturnpurefunit

于 2013-11-06T08:08:51.567 に答える
2

return不可能なファンクターの最も単純な例は次の(,) aとおりです。

instance Functor ((,) a) where
  fmap f (a, x) = (a, f x)

しかし、これをモナドにするには、 を実装するためreturnに、何もないところから値を生成する必要がありaます (あらゆる型に対して!)。それを行う唯一の方法return x = (undefined, x)は、ほとんど解決策ではありません...

于 2013-11-06T01:07:01.737 に答える