lifting
モナドスタックが深くなるとlist $ lift $ lift $ fooのようにしないといけない こう対応関係を見るとわかりやすい
fmap
liftM
モナドの関数
この表現、わかりにくくない?mrsekut.icon
普通の関数をモナド値に適用できる、とかのほうがわかり易くない?mrsekut.icon
理解するのはliftより簡単
lift
モナド変換子の関数
アクションを変換子層の一つ下のレベルから現在の層へ持ち上げ Monad m => (a1 -> r) -> m a1 -> m r
https://gyazo.com/dd6b98736d001ecb17ab9307b7d7ed51
MonadTrans型クラスの中で定義されている
lift :: (Monad m) => m a -> t m a
tはモナド変換子
「持ち上げ」と訳される
モナドからモナド変換子を生成する
モナド変換子版のreturn
liftすることで内側のモナドアクションを使えるようになる
code:hs
import Control.Monad.State
a :: StateT String IO ()
a = do
v <- get -- Stateアクション
lift $ print v -- IOアクション
main = do
runStateT a "hello"
code:hs
class MonadTrans t where
lift :: Monad m => m a -> t m a
IOモナドはモナドスタックの常に最深部にいる
そこまでlift $ lift $ lift $ ..と繰り返していくのが面倒なので、liftIOで一発でそこまでliftingできる
MonadIO型クラス内で定義されている
code:hs
class (Monad m) => MonadIO m where
liftIO :: IO a -> m a
instance MonadIO IO where
liftIO = id
https://gyazo.com/803d59e2f91668786d5a5352f427cb96
lifting則
実際に「lifting則」という名前がついているのかは知らないmrsekut.icon
mrsekut.iconが適当に言っている
liftingにもモナド則のような法則がある ref code:hs
-- 1
lift . return = return
-- 2
lift (m >>= f) = lift m >>= (lift . f)
参考