25

Functorのfmapのタイプは次のとおりです。

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

最初に関数(a-> b)をfaのパラメーターに適用して、タイプbの結果を作成し、次にfを適用すると、結果はfbのようになります。

Maybe aたとえば、次を使用します。

 fmap show (Just 1)
 result is : Just "1"

言うのと同じ:

Just (show 1)

しかし、いつ(->)ファンクターとして使用されるか(でControl.Monad.Instances

import Control.Monad.Instances
(fmap show Just) 1
result is : "Just 1"

つまり、Just最初に適用され、次にshow適用されます。別の例では、結果は同じです。

 fmap (*3) (+100) 1
 result is 303

なぜ*3最初ではないの+100ですか?

4

5 に答える 5

34

(つまり関数)のfmapインスタンスは文字通り単なる構成です。ソース自体(->) rから:

instance Functor ((->) r) where
    fmap = (.)

したがって、あなたの例では、に置き換えfmap(.)、いくつかの変換を行うことができます

fmap (*3) (+100) 1 => 
(.) (*3) (+100) 1  =>
(*3) . (+100) $ 1  => -- put (.) infix
(*3) (1 + 100)     => -- apply (+100)
(1 + 100) * 3         -- apply (*3)

つまり、fmapfor関数はそれらを右から左に構成します(とまったく同じですが(.)、それは賢明です(.))。

別の見方をすると((二重の)確認のために!)、型アノテーションを使用できます。

-- general fmap
fmap :: Functor f => (a -> b) -> f a -> f b

-- specialised to the function functor (I've removed the last pair of brackets)
fmap :: (a -> b) -> (r -> a) -> r -> b 

したがって、最初に型の値(3番目の引数)を(関数によって)r型の値に変換する必要があります。これにより、関数はそれを型の値(結果)に変換できます。ar -> aa -> bb

于 2012-04-24T08:36:05.927 に答える
26

Functorのfmapのタイプは次のとおりです。

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

最初に関数(a-> b)をfaのパラメーターに適用して、タイプbの結果を作成し、次にfを適用すると、結果はfbのようになります。

それはのタイプですがfmap、そのタイプが何を意味するかについてのあなたの解釈は間違っています。

f aには1つのパラメーターがあり、そのパラメーターのタイプは。であると想定しているようですa

考えてみてくださいxs :: [a]

  • おそらくxs = []
  • おそらくxs = [x1]
  • おそらくxs = [x1, x2]
  • ..。

タイプ は、単一のタイプパラメーターを持つファンf aクターです。ただし、上記の1番目と3番目のケースからわかるように、 typeのは必ずしも形式をとる必要はありません。faf aF x

今考えてみましょうfmap f xs

  • おそらくfmap f xs = []
  • おそらくfmap f xs = [f x1]
  • おそらくfmap f xs = [f x1, f x2]
  • ..。

必ずしも適用する必要はありませんf(最初のケース)!または、複数回適用する場合があります(3番目の場合)。

私たちがしていることは、タイプのものをタイプのものに置き換えることaですb。ただし、大きな構造はそのままにしておきます。新しい要素は追加されず、要素は削除されず、順序は変更されません。


それでは、ファンクターについて考えてみましょう(c ->)。(ファンクターは1つの型パラメーターのみを受け取るため、への入力(->)は固定されていることに注意してください。)

c -> aも含まれていaますか?sがまったく含まれていない可能性がありますがa、を与えると、どういうわけか薄い空気から魔法のようなものになる可能性がありますc。しかし、からの結果にfmapはタイプがあります。が表示されたときに、その中c -> bからを提供するだけで済みます。bc

だから私たちは言うことができますfmap f x = \y -> f (x y)

この場合、fオンデマンドで適用しています---返される関数が適用されるたびに、f同様に適用されます。

于 2012-04-24T08:50:49.083 に答える
20

タイプを機能させるには、そのように定義する必要があります。ご指摘のとおり、タイプfmapは次のとおりです。

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

ファンクターf((->) c)

注:(c ->)実際には、これを、つまりからの関数として記述したいcのですが、Haskellではこれを実行できません。)

次にf a、実際((->) c a)には、と同等(c -> a)であり、同様にf b、であるため、次のようになります。

fmap :: (a -> b) -> (c -> a) -> (c -> b)

つまり、次の2つの機能を実行する必要があります。

  • f :: a -> b
  • g :: c -> a

新しい関数を作成します

  • h :: c -> b

ただし、これを行う方法は1つしかありません。g最初に適用してタイプの何かを取得aし、次に適用fしてタイプの何かを取得する必要がbあります。つまり、定義する必要があります。

instance Functor ((->) c) where
    fmap f g = \x -> f (g x)

または、より簡潔に、

instance Functor ((->) c) where
    fmap = (.)
于 2012-04-24T08:41:44.213 に答える
6

fmapfor(->)はのように定義されfmap = (.)ます。だから、(fmap f g) x です。あなたの場合、これはに等しい結果になります。 (f . g) xf (g x)(*3) ((+100) 1)3 * (100 + 1)303

于 2012-04-24T08:34:34.220 に答える
1

関数型を作成するには、(->)の2種類のパラメーター、つまり単一の入力引数型と戻り型が必要です。

Functorは1つの型パラメーターしか受け取れないため、入力引数の型を特定する必要があります(左から右への最初の型であるため)。これにより、関数の戻り型がFunctorの型パラメーターになります。

したがって、関数(ファンクター)a-> bの場合、機能するには、fmapにa->xxx以外のタイプb->xxxの関数ffを指定する必要があります。つまり、関数ffはa->bの後にのみ適用できます。適用されます。

于 2018-01-06T09:07:38.583 に答える