2016-04-25 12 views
1

で等式推論を破るI、そのまま運用パッケージドゥGADTsはHaskellの

{-# LANGUAGE GADTs #-} 
import Control.Monad ((<=<)) 
import Control.Monad.Operational 

data Motor' a where 
    --Define GADT 

serialNewportT :: (Monad m, MonadIO m) => ProgramT Motor' m a -> m a 
serialNewportT = eval <=< viewT 
    where 
    eval :: (Monad m, MonadIO m) => ProgramViewT Motor' m v -> m v 
    eval (Return x) = return x 
    eval (x :>>= k) = f x >>= serialNewportT . k 

f :: (Monad m, MonadIO m) => Motor' a -> m a 
f = undefined -- excluded for brevity 

コードからProgramTを使用して、以下のインタプリタは、現在、うまくチェックを入力しています。しかし、私はインタープリタが異なるモーターをどのように扱うかを切り換えたいので、fをハードコードではなくパラメータにしたいと思っています。次のコードでこのスイッチを作ろうとしました。

{-# LANGUAGE GADTs #-} 
import Control.Monad ((<=<)) 
import Control.Monad.Operational 

data Motor' a where 
    --Define GADT 

serialNewportT :: (Monad m, MonadIO m) => (Motor' a -> m a) -> ProgramT Motor' m a -> m a 
serialNewportT f = eval <=< viewT 
    where 
    eval :: (Monad m, MonadIO m) => ProgramViewT Motor' m v -> m v 
    eval (Return x) = return x 
    eval (x :>>= k) = f x >>= serialNewportT f . k 
私はちょうど同じタイプのローカル1でグローバル名を交換していますので

しかし、このコードは、エラーメッセージ

Couldn't match type ‘b’ with ‘c’ 
    ‘b’ is a rigid type variable bound by 
     a pattern with constructor 
     :>>= :: forall (instr :: * -> *) (m :: * -> *) a b. 
       instr b -> (b -> ProgramT instr m a) -> ProgramViewT instr m a, 
     in an equation for ‘eval’ 
    ‘c’ is a rigid type variable bound by 
     the type signature for 
     serialNewportT :: (Monad m, MonadIO m) => 
          (Motor' c -> m c) -> ProgramT Motor' m a -> m a 
Expected type: Motor' c 
    Actual type: Motor' b 

で失敗し、私はそれが滞りなく働いているべきであると考えているだろう。パラメータとしてfを使用して統一する型を取得するにはどうすればよいですか?

+7

は、あなただけの上位タイプを必要としています。元のコードでは、任意の 'a '型に対して' Motor' a'型でインスタンス化することができますが、非動作型コードでは 'ProgramT Motor 'ma'と全く同じ型です一方、関数本体では、他の(存在する場合は量子化された)型 'b'に対して' Motor 'b''で 'f'を呼び出します。 'serialNewportT ::(Monad m、MonadIO m)=>(forall xモーター 'x - > mx) - > Programmotモーター' ma - > ma' – user2407038

+5

@ user2407038は答えのようです私には – Carsten

+0

ええ。スコープ付きの型変数を調べて、すべてを一致させようとしましたが、ランクN型は見ていませんでした。私はそれが最終的にそれらを学ぶ時だと思います。 @ user2407038、これを回答したい場合は、そのクレジットをお渡しします。 – user640078

答えて

2

fの種類を正しく翻訳していません。元のコードでは、fのタイプはforall a . (..) => Motor' a -> m aです。関数本体で使用すると、他のいくつかのためにMotor' bfを呼ぶのに対し、(それの型が正確ProgramT Motor' m aのようにa同じであることを任意のa用タイプMotor' aでインスタンス化していますが、状態非稼働コードでできること現存する量子化された)タイプb。あなたは正しくF` `の種類を翻訳していない

serialNewportT :: (Monad m, MonadIO m) => (forall x . Motor' x -> m x) -> ProgramT Motor' m a -> m a 
関連する問題