35336
「プログラミングHaskell」を勉強していて、9章サンプルコードが実行できず困っています。  
<https://github.com/macalimlim/programming-in-haskell/blob/master/Chapter9.hs>  
以下のコードを実行しようととすると、このようなエラーが出てしまいました。  
どなたか詳しい方、ご助言頂けるとありがたいです。。

```

    Parsing.hs:8:10: error:
        • No instance for (Applicative Parser)
            arising from the superclasses of an instance declaration
        • In the instance declaration for ‘Monad Parser’
    
    Parsing.hs:14:10: error:
        • No instance for (GHC.Base.Alternative Parser)
            arising from the superclasses of an instance declaration
        • In the instance declaration for ‘MonadPlus Parser’
    
```

コード

```

    module Parsing where
    
    import Data.Char
    import Control.Monad
    
    newtype Parser a = P (String -> [(a, String)])
    
    instance Monad Parser where
        return v = P (\inp -> [(v, inp)])
        p >>= f  = P (\inp -> case parse p inp of
                              [] -> []
                              [(v, out)] -> parse (f v) out)
    
    instance MonadPlus Parser where
        mzero       = P (\inp -> [])
        p `mplus` q = P (\inp -> case parse p inp of
                                 [] -> parse q inp
                                 [(v, out)] -> [(v, out)])
    
    parse :: Parser a -> String -> [(a, String)]
    parse (P p) inp = p inp
    
```
CC BY-SA 3.0
2017-06-06T02:38:24.507
35326
2017-06-06T08:20:04.460
3653
question
haskell
Haskellで以下のエラーが出てしまう
GHC 7.10 からは仕様が変わって上のようなコードはコンパイルが通らなくなりましたが，対応は簡単です．

* * *

GHCの7.10からは [Functor-Applicative-Monad
Proposal](https://wiki.haskell.org/Functor-Applicative-Monad_Proposal)
という名前で知られている変更が入り，

  * [`Applicative`](http://hackage.haskell.org/package/base-4.9.1.0/docs/Control-Applicative.html#t:Applicative) が [`Monad`](http://hackage.haskell.org/package/base-4.9.1.0/docs/Prelude.html#t:Monad) の親クラスに
  * [`Alternative`](http://hackage.haskell.org/package/base-4.9.1.0/docs/Control-Applicative.html#t:Alternative) が [`MonadPlus`](http://hackage.haskell.org/package/base-4.9.1.0/docs/Control-Monad.html#t:MonadPlus) の親クラスに

なりました．つまり， 何かを `Monad` のインスタンスにしようと思うと，`Applicative`
のインスタンスにもしておくことが必要になったということです．以前はこの制約はありませんでしたが，意味的にはこのようにしておいたほうが色々とよいということで，移行がスムーズにできるように気を配りながら導入されることになりました．

従ってコードを修正するには，

  * `Parser` を `Applicative` と（そのために，その親クラスである）[`Functor`](http://hackage.haskell.org/package/base-4.9.1.0/docs/Prelude.html#t:Functor) に
  * さらに `Alternative` に

することが必要になります．具体的な変更点は [GHC 7.10
の移行ガイド](https://ghc.haskell.org/trac/ghc/wiki/Migration/7.10#GHCsaysNoinstanceforApplicative...)や
[HaskellWiki](https://wiki.haskell.org/Functor-Applicative-
Monad_Proposal#Future-proofing_current_code) に書かれていますが，前者のおすすめに従うと次のようになります．

```

    module Parsing where
    
    import Data.Char
    import Control.Monad
    import Control.Applicative (Alternative(..))
    -- ちょっと面倒ですが
    
    newtype Parser a = P (String -> [(a, String)])
    
    instance Functor Parser where
        fmap = liftM
    instance Applicative Parser where
        pure v = P (\inp -> [(v, inp)]) -- ここに，Monad の return で書いていたコードを移す
        (<*>) = ap
    
    instance Monad Parser where
        -- return はデフォルトで Applicative の pure なので，ここには不要
        p >>= f  = P (\inp -> case parse p inp of
                            [] -> []
                            [(v, out)] -> parse (f v) out)
    
    instance Alternative Parser where
        (<|>) = mplus
        empty = mzero
    
    instance MonadPlus Parser where
        mzero       = P (\inp -> [])
        p `mplus` q = P (\inp -> case parse p inp of
                                [] -> parse q inp
                                [(v, out)] -> [(v, out)])
    
    parse :: Parser a -> String -> [(a, String)]
    parse (P p) inp = p inp
    
```

実際には `MonadPlus` も `Alternative` をもとにデフォルト実装があるので，`MonadPlus` で書いてあるコードをまるっと
`Alternative` に移したほうがより良いようです．今回は書き換えの負担と相談という感じでしょうか．

`7.10` 以前のバージョンの GHC
を用意するのも1つの手ですが（たとえば7.8），個人的にはおまじないを足しつついまお使いの新しいバージョンをそのまま使うほうが良いと思います．
CC BY-SA 3.0
2017-06-06T08:12:30.443
35336
2017-06-06T08:20:04.460
2017-06-06T08:20:04.460
2901
2901
35326
answer