2016-08-27 4 views
-4

ここに私のコードです。コンパイルするときタイプミスマッチエラーが発生するのはなぜですか?

{-# LANGUAGE MultiParamTypeClasses #-} 
{-# LANGUAGE FlexibleInstances #-} 

module StateParser where 
import Control.Monad 
import Control.Applicative 

newtype State s a = State {compute :: s -> (a, s)} 

newtype StateM m s a = StateM {compute_M :: s -> m (a, s)} 

result_s :: a -> State s a 
result_s v = State (\s -> (v ,s)) 

bind_s :: State s a -> (a -> State s b) -> State s b 
bind_s st f = State $ \s -> (\(v, s') -> compute (f v) s') (compute st s) 

result_sm :: (Functor m) => a -> StateM m s a 
result_sm v = StateM (\s -> result_s (v, s)) 

bind_sm :: (Functor m) => StateM m s a -> (a -> StateM m s b) -> StateM m s b 
bind_sm stm f = StateM $ \s -> (tmp s `bind_sm` id) 
    where 
    tmp s = fmap (\(v, s') -> compute_M (f v) s') (compute_M stm s) 

instance Functor (State s) where 
    fmap f st = st >>= (pure . f) 

instance Applicative (State s) where 
    pure = result_s 
    p <*> q = p >>= \f -> 
      q >>= (pure . f) 

instance Monad (State s) where 
    --Explicit return definition only required for code required to be compatible 
    --with GHC versions prior to 7.10. The default implementation for all GHC 
    --versions from 7.10 is 
    return = pure 
    (>>=) = bind_s 

instance Functor f => Functor (StateM f s) where 
    fmap f stm = stm `bind_sm` (result_sm . f) 

instance Applicative f => Applicative (StateM f s) where 
    pure = result_sm 
    p <*> q = p `bind_sm` \f -> 
      q `bind_sm` (pure . f) 

instance Monad m => Monad (StateM m s) where 
    return = pure 
    (>>=) = bind_sm 

、私は2種類の不一致エラーを取得:

StateParser.hs:43:29 
    Couldn't match type `m' with `State s1' 
     `m' is a rigid type variable bound by 
      the type signature for result_sm :: Functor m => a -> StateM m s a 
      at StateParser.hs:42:14 
    Expected type: m (a, s) 
     Actual type: State s1 (a, s) 
    ... 
    In the expression: result_s (v, s) 
    In the first argument of `StateM', namely 
     `(\ s -> result_s (v, s))' 

StateParser.hs:46:33: 
    Couldn't match type `m' with `StateM m0 s0' 
     `m' is a rigid type variable bound by 
      the type signature for 
      bind_sm :: Functor m => 
         StateM m s a -> (a -> StateM m s b) -> StateM m s b 
      at StateParser.hs:45:12 
    Expected type: StateM m0 s0 (m (b, s)) 
     Actual type: m (m (b, s)) 
    ... 
    In the first argument of `bind_sm', namely `tmp s' 
    In the expression: (tmp s `bind_sm` id) 

しかし、私は非常に明確にそれらを一致させることができなければならないタイプのコンストラクタState sStateM f sためFunctor型クラスのインスタンスを、定義されていますタイプ変数mでは、Functorの型付きがbind_smおよびresult_smにバインドされています。

おそらく私が知らないハスケルの型推論手続きのいくつかの側面があります。誰かが私を啓発するだろうか?

+0

ここでは魔法はありません。あなたの機能は単に間違っています(タイプは正しくありません)。タイプチェッカーは完全に正しいです。コンパイラはなぜプログラムが間違っているのかをあなたに正確に伝えてくれたので、あなたが間違っていると言うことを修正しようとしましたか?最低でも、 'StateM $ \ s - > .. \' bind_sm \ '..'は' StateM'が 's - > StateM m0 x0(StateM m1 x1 a、s)) '明らかにそうではありません。 – user2407038

答えて

4
result_sm v = StateM (\s -> result_s (v, s)) 

私に間違って見えます。機能

\s -> result_s (v, s) 

StateMm ~ State sだけでなく、任意のmため

s -> m (a,s) 

を期待しながら

s -> State s (a,s) 

を入力しています。

result_sm :: (Monad m) => a -> StateM m s a 
result_sm v = StateM (\s -> return (v, s)) 

(または応用的バリアント):

はあなたのような何かをしたくないあなたはよろしいですか?

+2

上記のコードまたはユーザーに関連するエラーですか?後者は、タイプシグネチャを変更する必要があるため、理解できます。 – chi

+2

@UnchartedWaters、あなたは自分自身のためにあまり役に立ちません。コード@chiは、ここに示したように 'result_sm'の問題を修正したことを示しています:http://lpaste.net/180892あなたは' bind_sm'などの他の問題がありますが、これは最初のエラーの修正です。 – ErikR

関連する問題