返信ありがとうございます。
自分の説明が足りなかったり、そもそも以前書いたときの自分の理解も足りなくて混乱を招く説明してたので、ちょっと話が食い違ってる?感じがします。
質問の回答になるかわかりませんが、最初に投稿した後に色々考えて理解も進んだので、もう一度現状の自分の考えを説明してみます。
まず、現在のApply自体は、おそらくApply則そのものは満たします。(Apply則は以下のもの)
https://github.com/ekmett/semigroupoids/blob/v4.0/src/Data/Functor/Bind.hs#L95
ただし、それが(現在のmasterにある)ApplicativeやMonadとの整合性がない、というのがポイントです。
(ここで、CofreeをApplyにするために、どのような制約が必要か?はあまり重要な問題ではありません)
現在のCofreeのApplyは
instance Apply f => Apply (Cofree f) where
(f :< fs) <.> (a :< as) = f a :< ((<.>) <$> fs <.> as)
(f :< fs) <. (_ :< as) = f :< ((<. ) <$> fs <.> as)
(_ :< fs) .> (a :< as) = a :< (( .>) <$> fs <.> as)
となってますが、整合性保つためには、単にApplicativeの定義とほぼ同じように以下のようにするべきでは?
という考えになりました
instance Alternative f => Apply (Cofree f) where
(<.>) = ap
https://github.com/ekmett/free/blob/b229616f69/src/Control/Comonad/Cofree.hs#L149-L155
また、じゃあ最初のころ(v3.2以前)に存在していたApplicativeやApplyのインスタンスはなんだったのか?
間違いだったのか?というとそうでもなくて
https://github.com/ekmett/free/blob/v3.2/src/Control/Comonad/Cofree.hs#L127-L141
「CofreeをApplyやApplicativeにする方法は2種類存在する」
のだという考えに至りました。
(おそらく、ListがZipListとして別の方法でApplicativeのインスタンスにするのが可能なのにちょうど対応する)
なので、v3.2の頃の定義も正しくて、本当は新しくCofreeのnewtypeを定義して、その定義を残しても良かったのではないかと思います。
結局歴史的には
1. ApplyやApplicativeのインスタンスが定義された(この時点ではMonadのインスタンスは無いし、Functor含めそれらに整合性がある)
2. Monadのインスタンスが追加された
3. 追加したMonadのインスタンスと、最初に存在していたApplicativeのインスタンスに整合性がないことがわかった
4. Applicativeの古い定義は消されて、Monadのインスタンスと整合性を保つために定義が変わった(古い定義はnewtypeにして残すべきだったかもしれないが、Monadと合わせるという意味でのこの修正自体は正しい)
5. Applicativeの修正の際にApplyも同時に修正するべきだった(?)が、修正漏れに自分が気づいた(イマココ
ということだと思います。
issue欄にコメントしたら、「そうだね、多分間違ってるね」的な返信がekmettからきたけど、
https://github.com/ekmett/free/issues/36#issuecomment-30728047
まだ、コードの修正はされてません。
2013年12月18日 13:55 <
nobu_t...@nifty.com>: