2016-05-11 13 views
0
type Context = Map.Map VarName (Type, Integer) 
type Memory = Map.Map Integer LitVal 
type Functions = Map.Map VarName (Stmt, Context) 

data InterpreterM stmts a = ExeInterpreter stmts a | PropInterpreter stmts a 

newtype InterpreterMT stmts m a = InterpreterMT { runInterpreterMT :: stmts -> m (InterpreterM stmts a) } 

type Interpreter = InterpreterMT Stmts (StateT (Memory, Functions) (ReaderT (Context, Context) (ErrorT String IO))) 



instance (Monad m) => Monad (InterpreterMT s m) where 
    return x = InterpreterMT $ \stmts -> return (ExeInterpreter stmts x) 
    x >>= f = InterpreterMT $ \stmts -> do 
     m <- runInterpreterMT x stmts 
     case m of 
      (ExeInterpreter ss a) -> (runInterpreterMT (f a) ss) 

data Stmts = Statements Stmt Stmts | EmptyStmts 

    nextStatement :: <HERE> 

こんにちは、 ご覧のとおり、Stmtsには再帰的な定義があります。今、私はnextStatementの機能を実装したいと思いますが、私はモナドでそれを行う方法を想像できません。 モナドを超えて、それは簡単ですが、その後、文は私が意味する、提供する必要があります。モナドのフィールド。 Haskell

nextStatement :: Stmts -> Stmt 
nextStatement (Statements s ss) = s 
nextStatement EmptyStatement = EmptyStatement 
+0

を書くことができるのだろうか?私はあなたが 'nextStatement'を定義するのと同じ問題は、空のリストに' head :: [a] - > a'を定義しようとするのと同じだと思います。あなたはすることはできません、そして、それは 'head []'がエラーを投げる理由です。 – ErikR

+0

少なくともあなたの問題を再現できる十分なコードを含めることは丁寧です。これは、インポートと、必要なすべての型定義を意味します。 'VarName'、' Type'、 'LitVal'、' Stmt'とは何ですか?私たちはこのことを突き詰めることができますが、将来的には最小の実例を含めてください。 –

+0

@DanielWagnerあまりにも多くのコードを置かないようにしたいと思っていました。私は今すぐ添付することができます。 – Gilgamesz

答えて

1

私はあなたがおそらくこのような何かしたいと思います。特にInterpreter

nextStatement :: MonadError String m => Stmts -> m Stmt 
nextStatement (Statements s _) = return s 
nextStatement EmptyStmts = throwError "nextStatement EmptyStmts" 

MonadError Stringのインスタンスであるので、これはタイプStmts -> Interpreter Stmtとすることもできます。あなたは(私はちょうど1を選んだ私は適切であるかわからない)ExeInterpreterまたは適切なPropInterpreterのいずれかで注釈を付け、通常のState様の方法でInterpreterMT変圧器からStmtsを取得することができます。

getStmts :: Monad m => InterpreterMT stmts m stmts 
getStmts = InterpreterMT (\stmts -> return (ExeInterpreter stmts stmts)) 

あなたがすべきおそらくInterpreterMTの通常のインターフェイスを実装して、MonadTrans (InterpreterMT stmts)のインスタンスと、たぶんMonadError e m => MonadError e (InterpreterMT stmts m)のいくつかの+ mtlクラスのインスタンスを実装します。そして、あなたは `EmptyStatement`は` Stmt`、ない単一 `Stmt`のリストのようなものですので、なぜそれが` nextStatement`からの戻り値として有効であることが表示されます

getStmts >>= nextStatement :: MonadError String m => InterpreterMT Stmts m Stmt 
+0

いいえ、 'Stmts'は' InterpreterMT'モナドのフィールドです。関数の引数として取得しています。 – Gilgamesz

+0

@Gilgamesz Ugh、なぜあなたの 'InterpreterMT'トランスフォーマーはこのようなラウンドアバウトで設定されていますか?とにかく、私に瞬間を与え、私は醜さに対処する方法を示します。 –

+0

"おそらくMonadTrans(InterpreterMT stmts)のインスタンスと、おそらくMonadError em => MonadError e(InterpreterMT stmts m)+他のmtlクラスのインスタンスを与えるInterpreterMTの通常のインタフェースを実装するべきです。書き込み " 私は何を意味するのか分かりません。 – Gilgamesz

関連する問題