寛解と機械的な答えのお詫び。私はApplicativeやMonadのようなチェリーピッキングのものは好きではありませんが、どこにいるのかはわかりません。これはnot my usual approach to teaching Haskellです。
まず、ap
は実際にはフードの下で(<*>)
です。
これはどういう意味ですか?つまり、私たちが何をしているのかを記述するために、モナドのように「強い」ものが必要なわけではありません。適用は十分です。しかし、Functorはしません。 、把握する
Prelude> ap (Just (+1)) (Just 1)
Just 2
Prelude> (<*>) (Just (+1)) (Just 1)
Just 2
まず最初は、ある型クラスのApplicativeのどのインスタンス私たちは話している。
Prelude> :info Applicative
class Functor f => Applicative (f :: * -> *) where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
Prelude> :info Functor
class Functor (f :: * -> *) where
fmap :: (a -> b) -> f a -> f b
ここではたぶんモナド/ Applicativeのでap
/(<*>)
ですか?
Prelude> :t fromMaybe
fromMaybe :: a -> Maybe a -> a
脱糖fromMaybeのタイプは少しは私達を与える:
(->) a (Maybe a -> a)
だから私たちはここに関係しているタイプのコンストラクタは(->)
です。 GHCiから関数型としても知られている(->)
について教えてください。
Prelude> :info (->)
data (->) a b -- Defined in ‘GHC.Prim’
instance Monad ((->) r) -- Defined in ‘GHC.Base’
instance Functor ((->) r) -- Defined in ‘GHC.Base’
instance Applicative ((->) a) -- Defined in ‘GHC.Base’
Hrm。たぶんどうですか?
Prelude> (+1) 1
2
Prelude> (+1) `fmap` Just 1
Just 2
Prelude> Just (+1) <*> Just 1
Just 2
Prelude> :t fmap
fmap :: Functor f => (a -> b) -> f a -> f b
Prelude> let mFmap = fmap :: (a -> b) -> Maybe a -> Maybe b
Prelude> (+1) `mFmap` Just 1
Just 2
Prelude> :t (<*>)
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
Prelude> let mAp = (<*>) :: Maybe (a -> b) -> Maybe a -> Maybe b
Prelude> :t (+1)
(+1) :: Num a => a -> a
Prelude> :t Just (+1)
Just (+1) :: Num a => Maybe (a -> a)
Prelude> Just (+1) `mAp` Just 1
Just 2
さて、どのような関数型のファンクタとApplicativeの程度:
たぶんため
(<*>)
を利用して何が起こっ
Prelude> :info Maybe
data Maybe a = Nothing | Just a -- Defined in ‘GHC.Base’
instance Monad Maybe -- Defined in ‘GHC.Base’
instance Functor Maybe -- Defined in ‘GHC.Base’
instance Applicative Maybe -- Defined in ‘GHC.Base’
は、このでしたか?ここで難しい部分の1つは、(->)
が部分的にのに適用され、Functor/Applicative/Monadとなることです。したがって、f
は(->) a b
の(->) a
になります。ここで、a
は引数型であり、結果はb
です。
Prelude> (fmap (+1) (+2)) 0
3
Prelude> (fmap (+1) (+2)) 0
3
Prelude> :t fmap
fmap :: Functor f => (a -> b) -> f a -> f b
Prelude> let funcMap = fmap :: (a -> b) -> (c -> a) -> c -> b
Prelude> -- f ~ (->) c
Prelude> (funcMap (+1) (+2)) 0
3
Prelude> :t (<*>)
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
Prelude> let funcAp = (<*>) :: (c -> a -> b) -> (c -> a) -> (c -> b)
Prelude> :t fromMaybe
fromMaybe :: a -> Maybe a -> a
Prelude> :t funcAp fromMaybe
funcAp fromMaybe :: (b -> Maybe b) -> b -> b
Prelude> :t const
const :: a -> b -> a
Prelude> :t funcAp const
funcAp const :: (b -> b1) -> b -> b
有用であるとは限りません。 funcAp const
は、型からだけでなく、パラメトリシティの仕組みを知ることができます。
編集:作成者については、ファンクタ(->) a
はちょうど(.)
です。それが適用されますが、追加の引数があります。 MonadはApplicativeですが、引数が反転されています。
さらなるwhuttery:適用の場合)はSKIコンビネータ計算のKであり、pure
はKです。あなたは中置構文を好むならば、あなたが探しているモナドが(->) r
またはr -> _
ある
Prelude> :t pure
pure :: Applicative f => a -> f a
Prelude> :t const
const :: a -> b -> a
Prelude> :t const
const :: a -> b -> a
Prelude> let k = pure :: a -> b -> a
Prelude> k 1 2
1
Prelude> const 1 2
1
これは私を夢中にさせてくれて嬉しく思っています。x.x – dcastro
ところで、 'ap fromMaybe'は本当のプログラムに誰も書いてくれないだろうという難読化されたコードです。 –