2

doブロックの内部では、モナドからその内容を「抽出」して描画できることを知っています。たとえば、署名付きの関数がある場合:

myFunction :: MyReader (Set Int)

doブロック内でこれを行うことができます:

mySet <- myFunction

これにより、Set Int私が望むものが得られます。ただし、引数を取るように関数を変更すると、次のようになります。

myFunction :: Int -> MyReader (Set Int)

やりたいことができなくなった:

myFunction' <- myFunction

これはエラーでコンパイルに失敗しCouldn't match expected typeProbable cause: ‘myFunction'’ is applied to too few arguments. このようなことを試みることは、構文的にも正しくありません:

myFunction' x <- myFunction x

myFunction'私はタイプになりたいですInt -> Set Int。私は自分がやりたいことをする方法を理解できないか、どこにも見つけられません。誰でも助けてもらえますか?

4

2 に答える 2

1

これはあなたが探しているものかもしれません: (未テスト)

data MyEnv = MyEnv { myFn :: Int -> Set Int }
type MyReader a = Reader MyEnv a

myFunction :: Int -> MyReader (Set Int)

something = do
     ...
     myFunction' <- reader (\env x -> runReader (myFunction x) env)
     -- here myFunction' :: Int -> Set Int

ただし、抽象化を壊して再構築するため、ちょっと醜いです。もっときれいな方法があるかもしれませんが、任意のモナドで同じことを行うのは不可能なので、どうにかして抽象化を破る必要があります。

少なくとも、ヘルパー関数で詳細を保持できます。

flipReader :: (a -> Reader b c) -> Reader b (a -> c)
flipReader r = reader (\y x -> runReader (r x) y)

その後:

something = do
    ...
    myFunction' <- flipReader myFunction
于 2014-11-01T13:42:25.220 に答える