0

だから私は(->) rReader モナドのインスタンスであると言われていますが、これがどのように機能するかの具体的な例を見つけることができないようです. 一部のコードを Reader で明示的にラップすることなく、これを使用したい

import Control.Monad.Reader

testOne :: Reader String String
testOne = do
  env <- ask
  return $ "Hello, " ++ env

testTwo :: String -> String
testTwo = do
  env <- ask
  return $ "G'day, " ++ env

実行runReader testOne "there"はうまくいきますが、実行runReader testTwo "mate"は次のメッセージで見事に失敗します:

Couldn't match type ‘String -> String’
                   with ‘ReaderT [Char] Data.Functor.Identity.Identity a’
    Expected type: Reader [Char] a
      Actual type: String -> String

それで、私はここで何が欠けていますか?

4

2 に答える 2

2

runReader :: Reader r a -> r -> a特にReader避けたいnewtype専用です。testTwoは単なる関数なので、単純に を使用しますtestTwo "mate"

を一般的な方法で実行したい場合はMonadReader、独自の型クラスを定義できます。おおよそ次のようになります (未テスト):

class MonadReader r m => RunReader r m | m -> r where
  type Output m a :: *
  runReader' :: m a -> r -> Output m a

instance RunReader r ((->) r) where
  type Output ((->) r) a = a
  runReader' = ($)

instance Monad m => RunReader r (ReaderT r m) where
  type Output (ReaderT r m) a = m a
  runReader' = runReaderT

instance RunReader r m => RunReader r (MaybeT m) where
  type Output (MaybeT m) a = Output m (Maybe a)
  runReader' = runMaybeT . runReader'

-- any other instances

そして、runReader' testOne動作しrunReader' testTwoます。hereの使用の説明については、「関連するデータと型のファミリ」を参照しtypeてください。

于 2015-12-27T16:09:03.273 に答える