haskell-jp / questions #99 at 2022-01-09 16:33:51 +0900

こんな感じの関数を書きたいのですが、型エラーの直し方が分かりません!
(詳細なエラーをスレッドに貼ります)
liftToReader
  :: forall env m a. (MonadReader env m, MonadIO m)
  => (env -> IO a) -> m a
liftToReader f = reader $ \env ->
  (liftIO :: IO a -> m a) $ f env
発生したエラーの例:
src\Web\Slack\Classy.hs:232:18: error:
    • Occurs check: cannot construct the infinite type: a ~ m a
      Expected type: m a
        Actual type: m (m a)
    • In the expression:
        reader $ \ env -> (liftIO :: IO a -> m a) $ f env
      In an equation for 'liftToReader':
          liftToReader f = reader $ \ env -> (liftIO :: IO a -> m a) $ f env
    • Relevant bindings include
        f :: env -> IO a (bound at src\Web\Slack\Classy.hs:232:14)
        liftToReader :: (env -> IO a) -> m a
          (bound at src\Web\Slack\Classy.hs:232:1)
    |
232 | liftToReader f = reader $ \env ->
    |                  ^^^^^^^^^^^^^^^^...
ちょっと詳細な事情が分かってきました。実際は
reader :: (env -> a) -> m a

のところ、
reader :: (env -> m a) -> m a

として使おうとしているのが原因のようです。つまり後者のような reader があれば解決するはず...
こうか! reader なんか要らんかった!
liftToReader
  :: (MonadReader env m, MonadIO m)
  => (env -> IO a) -> m a
liftToReader f = do
  env <- ask
  liftIO $ f env