Control.Bifunctor
ってあったっけと思ったら、 category-extras にあったんですね。今は obsolete なパッケージですがControl.Bifunctor
ってあったっけと思ったら、 category-extras にあったんですね。今は obsolete なパッケージですがcabal new-freeze
で固定した依存関係を元に runhaskell Setup
を実行できれば、やりたかった事は概ね実現しそうです。「ghcのバージョンに合ったfreezeファイルをリネームしてからconfigureして下さい」みたいなビルド指示になるのかなf <$> t <*> u <*> v
<$>
(fmap) と <*>
の関係が、Applicative則に書いてないので、pure f <*> t <*> u <*> v
f <$> t <*> u <*> v
As a consequence of these laws, the Functor instance for f will satisfy
fmap f x = pure f <*> x
中でも一番重要なのは pure f <*> x = fmap f x
です。
と書いてあるのでこれを使えばいいのでないですか?他の則から導かれるようなものではないような?でも、さっき言及したApplicativeのドキュメントでは、
As a consequence of these laws, the Functor instance for f will satisfy
fmap f x = pure f <*> x
A minimal complete definition must include implementations of pure and of either <*> or liftA2. If it defines both, then they must behave the same as their default definitions:
(<*>) = liftA2 id
liftA2 f x y = f <$> x <*> y
[(+ 1), (+ 2)] <*> [1, 2]
f <$> x <*> y
の形ではないと思いますね. f <$> x <*> y
の形は実用上は良くでてくる形ですが, applicative style 一般の形がそうとは限らないと思います.一応id <$> [(+ 1), (+ 2)] <*> [1, 2]
<$>
があって、その次に pure
と <*>
が出てきます。<$>
は実は、 f <$> x = pure f <*> x
に分解できるという話です。(<$>)
は関数型(function type)の引数に適用できるので, a -> (b -> c)
のような型をもつ関数にも適用できます.someFunc :: a -> (b -> c)
という関数に (<$>)
を適用した値 (<$>) someFunc
の型は f (b -> c)
という関数っぽい型になります.f b
という型の値に適用できるように f b -> f c
という関数に変換して使いたくなるのが人情でしょう.f (a -> b) -> (f a -> f b)
という変換関数が欲しくなりますよね.それが, (<*>)
というわけです.(someFunc <$> (x :: f a)) <*> (y :: f b) ≡ (pure someFunc <*> (x :: f a)) <*> (y :: f b)
を満たして欲しいですよね.$
は右結合ですが, <$>
や <*>
は左結合です.これでハマった方を知っています.:sweat_smile:定義であって、Applicative 法則に含めるような規則じゃないと思います。でも、満たさないように
<*>
を実装することはできる(はず)なので、すごいH本やApplicativeのドキュメントに書いてあるとおり、則の一部であると解釈していいと思います。pure f <*> x = f <$> x
<$>
がメソッドから、単なる演算子に格下げされたら、法則が定義になる?<$>
は単なる演算子。 fmap
との関係を調べないといけないのか。fmap f x = pure f <*> x
は自動的に満たされるらしい。pure id <*> x = x
pure f <*> (pure g <*> x) = pure (.) <*> pure f <*> pure g <*> x = pure ((.) f g) <*> x = pure (f . g) <*> x
pure f <*> x
は関手法則を満たすので、 fmap
ですな。f <$> x = pure f <*> x
は満たされるので、これ自体は補題?ぐらいで、法則じゃなさそう。fmap' f x = pure f <*> x
fmap'
は, kazu さんがおっしゃるように Applicative law から Functor law を満たすことが示せます.fmap
が複数あれば(ここでの違いとは実装の違いではなく,振る舞いの違いであることに注意してください), fmap = fmap'
と一概には言えません.しかし,実は fmap の多相性からこれらは一意であることが知られています: https://wiki.haskell.org/Typeclassopedia#Lawsf <$> x = pure f <*> x
が導けます.これは定理ですね.なお,これは Applicative law が Functor law を含んでいるからですが,もう少し明確に分離できる別の Applicative law set も知られていて,(*) :: f a -> f b -> f (a, b) x * y = (,) <$> x <*> y unit :: f () unit = pure ()
fmap (f *** g) (u * v) = fmap f u * fmap g v
fmap snd (unit * v) = v
fmap fst (v * unit) = v
fmap (\(x, (y, z)) -> (x, y, z)) (u * (v * w)) = fmap (\((x, y), z) -> (x, y, z)) ((u * v) * w)
do { x <- mx; y <- f x; g x }
は左辺(と同じ意味の)の do { y <- h mx; g x }; h mx = do { x <- mx; f x }
に書き換えられるように「do の中の一部分を関数に切り出しても大丈夫だよ」という解釈の方がプログラミングでは役に立つ気がします。data Term = TermTrue | TermFalse | TermIf Term Term Term | TermZero | TermSucc Term | TermPred Term | TermIsZero Term deriving (Show)
Term
の中に Term
を入れることができるようになっています。