6

以下のコードを機能させようとしています。これは、function-as-next-stateを渡す有限状態マシンです。この関数はで呼び出されr、結果のリストと次のfunction-as-next状態を返します。リストがなくなるまで呼び出しを続け、結果の連結を返します。モナドは、必要に応じてエラーをスローできるようにするエラーモナドです。

fsm f []     = return []
fsm f (r:rs) = do
    (xs, f') <- f r
    rest     <- fsm f' rs
    return $ xs ++ rest

エラーは次のとおりです。

Occurs check: cannot construct the infinite type: t1 = t0 -> m0 ([a0], t1)
In the first argument of `fsm', namely f'

私は以前に無限の型エラーを見たことがあり、それを回避する方法は型を。でラップすることであると理解していnewtypeます。しかし、私はこれを行う方法を理解できません。

誰かが洞察を指摘できますか?

4

1 に答える 1

5

私はこれがあなたが望むものだと思います:

newtype F m = F { unF :: String -> m ([String], F m) }

fsm :: (Monad m) => F m -> [String] -> m [String]
fsm f []     = return []
fsm f (r:rs) = do
    (xs, f') <- unF f r
    rest     <- fsm f' rs
    return $ xs ++ rest

data再帰型が必要なとき、またはnewtypeいつでも使用する必要があるのは正しいことです。

コメントへの返信として、dup関数を実装する方法は次のとおりです。

dup :: (Monad m) => F m
dup = F dup' where dup' xs = return ([xs, xs], F dup')

...または、必要に応じて2つの別々の定義に分割することもできます。

型シグネチャがどうあるべきかわからない場合は、NoMonomorphismRestriction拡張機能を有効にするだけで、コンパイラは文句を言わず、最上位の型を正しく推測しないことに注意してください。

于 2013-03-18T23:57:55.920 に答える