Identity Monad

newtype Identity a = Identity { runIdentity :: a }

instance Functor Identity where
fmap = coerce instance Applicative Identity where
pure = Identity
(<*>) = coerce instance Monad Identity where
m >>= k = k (runIdentity m)
  • newtype Identity a = Identity { runIdentity :: a }

    Identity 类型是个 newtype,也就是对现有类型的封装。该类型只有一个类型参数 a。

    Identity a 封装了一个值:a,用 runIdentity 字段可以取出这个值。

    Identity 是一个用于占位的 Monad。

  • instance Monad Identity where

    对比 Monad 类型类的定义,可知 return 函数的类型签名为:

    return :: Identity a

    而 bind 函数的类型签名为:

    (>>=) :: a -> (a -> Identity b) -> Identity b

  • m >>= k = k (runIdentity m)

证明 Identity 符合Monad法则:
1. return a >>= f ≡ f a
return a >>= f ≡ Identity a >>= f ≡ f (runIdentity (Identity a)) ≡ f a
2. m >>= return ≡ m
m >>= return ≡ (Identity a) >> Identity ≡ Identity (runIdentity (Identity a)) ≡ Identity a ≡ m
3. (m >>= f) >>= g ≡ m >>= (\x -> f x >>= g)
(m >>= f) >>= g
≡ ((Identity a) >>= f) >>= g
≡ f (runIdentity (Identity a)) >> = g
≡ f a >> g
m >>= (\x -> f x >>= g)
≡ (Identity a) >>= (\x -> f x >>= g)
≡ (\x -> f x >>= g) (runIdentity (Identity a))
≡ (\x -> f x >>= g) a
≡ f a >> g

IdentityT Monad转换器

newtype IdentityT f a = IdentityT { runIdentityT :: f a }

instance (Monad m) => Monad (IdentityT m) where
return = IdentityT . return
m >>= k = IdentityT $ runIdentityT . k =<< runIdentityT m instance MonadTrans IdentityT where
lift = IdentityT instance (MonadIO m) => MonadIO (IdentityT m) where
liftIO = IdentityT . liftIO
  • newtype IdentityT f a = IdentityT { runIdentityT :: f a }

    IdentityT 类型是个 newtype,也就是对现有类型的封装。该类型有两个类型参数:内部 Monad 类型参数 f,以及值类型参数 a。

    IdentityT f 类型封装了一个封装在内部 Monad f 中的值:f a,用 runIdentity 字段可以取出这个值。

    Identity 是一个用于占位的 Monad转换器。

  • instance (Monad m) => Monad (IdentityT m) where

    如果 m 是个 Monad,那么 IdentityT m 也是一个 Monad。

    对比 Monad 类型类的定义,可知 return 函数的类型签名为:

    return :: IdentityT m a

    而 bind 函数的类型签名为:

    (>>=) :: a -> (a -> IdentityT m b) -> IdentityT m b

  • m >>= k = IdentityT $ runIdentityT . k =<< runIdentityT m

证明 IdentityT 符合Monad法则:
1. return a >>= f ≡ f a
return a >>= f
≡ (IdentityT . return) a >>= f
≡ IdentityT (m a) >>= f
≡ IdentityT $ runIdentityT . f =<< runIdentityT (IdentityT (m a))
≡ IdentityT $ runIdentityT . f =<< m a
≡ IdentityT $ runIdentityT (f a)
≡ f a
2. m >>= return ≡ m
假设 m = IdentityT (n a)
m >>= return
≡ IdentityT $ runIdentityT . return =<< runIdentityT m
≡ IdentityT $ runIdentityT . (IdentityT . return) =<< runIdentityT (IdentityT (n a))
≡ IdentityT $ runIdentityT . (IdentityT . return) =<< n a
≡ IdentityT $ runIdentityT (IdentityT (n a))
≡ IdentityT (n a) ≡ m
3. (m >>= f) >>= g ≡ m >>= (\x -> f x >>= g)
(m >>= f) >>= g
≡ (IdentityT $ runIdentityT . f =<< runIdentityT m) >>= g
≡ IdentityT $ runIdentityT . g =<< runIdentityT (IdentityT $ runIdentityT . f =<< runIdentityT m)
≡ IdentityT $ runIdentityT . g =<< (runIdentityT . f =<< runIdentityT m)
≡ IdentityT $ (runIdentityT m >>= runIdentityT . f) >>= runIdentityT . g
m >>= (\x -> f x >>= g)
≡ IdentityT $ runIdentityT . (\x -> f x >>= g) =<< runIdentityT m
≡ IdentityT $ runIdentityT . (\x -> IdentityT $ runIdentityT . g =<< runIdentityT (f x)) =<< runIdentityT m
≡ IdentityT $ (\x -> runIdentityT $ IdentityT $ runIdentityT . g =<< runIdentityT (f x)) =<< runIdentityT m
≡ IdentityT $ (\x -> runIdentityT . g =<< runIdentityT (f x)) =<< runIdentityT m
≡ IdentityT $ runIdentityT m >>= (\x -> runIdentityT (f x) >>= runIdentityT . g)
根据内部 Monad 的法则:(m >>= f) >>= g ≡ m >>= (\x -> f x >>= g)
IdentityT $ (runIdentityT m >>= runIdentityT . f) >>= runIdentityT . g
≡ IdentityT $ runIdentityT m >>= (\x -> (runIdentityT . f) x >>= runIdentityT . g)
≡ IdentityT $ runIdentityT m >>= (\x -> runIdentityT (f x) >>= runIdentityT . g)
证明 StateT 中 lift 函数的定义符合 lift 的法则。
1. lift . return ≡ return
lift . return $ a
≡ IdentityT (m a)
≡ return a
2. lift (m >>= f) ≡ lift m >>= (lift . f)
假设 m = n a 并且 f a = n b
于是 m >>= f = n b
lift (m >>= f)
≡ lift (n b)
≡ IdentityT (n b)
lift m >>= (lift . f)
≡ IdentityT (n a) >>= (\x -> lift . f $ x)
≡ IdentityT $ runIdentityT . IdentityT . f =<< runIdentityT (IdentityT (n a))
≡ IdentityT $ n a >>= f
≡ IdentityT (f a)
≡ IdentityT (n b)

Haskell语言学习笔记(26)Identity, IdentityT的更多相关文章

  1. Haskell语言学习笔记(88)语言扩展(1)

    ExistentialQuantification {-# LANGUAGE ExistentialQuantification #-} 存在类型专用的语言扩展 Haskell语言学习笔记(73)Ex ...

  2. Haskell语言学习笔记(79)lambda演算

    lambda演算 根据维基百科,lambda演算(英语:lambda calculus,λ-calculus)是一套从数学逻辑中发展,以变量绑定和替换的规则,来研究函数如何抽象化定义.函数如何被应用以 ...

  3. Haskell语言学习笔记(69)Yesod

    Yesod Yesod 是一个使用 Haskell 语言的 Web 框架. 安装 Yesod 首先更新 Haskell Platform 到最新版 (Yesod 依赖的库非常多,版本不一致的话很容易安 ...

  4. Haskell语言学习笔记(20)IORef, STRef

    IORef 一个在IO monad中使用变量的类型. 函数 参数 功能 newIORef 值 新建带初值的引用 readIORef 引用 读取引用的值 writeIORef 引用和值 设置引用的值 m ...

  5. Haskell语言学习笔记(39)Category

    Category class Category cat where id :: cat a a (.) :: cat b c -> cat a b -> cat a c instance ...

  6. Haskell语言学习笔记(72)Free Monad

    安装 free 包 $ cabal install free Installed free-5.0.2 Free Monad data Free f a = Pure a | Free (f (Fre ...

  7. Haskell语言学习笔记(44)Lens(2)

    自定义 Lens 和 Isos -- Some of the examples in this chapter require a few GHC extensions: -- TemplateHas ...

  8. Haskell语言学习笔记(38)Lens(1)

    Lens Lens是一个接近语言级别的库,使用它可以方便的读取,设置,修改一个大的数据结构中某一部分的值. view, over, set Prelude> :m +Control.Lens P ...

  9. Haskell语言学习笔记(30)MonadCont, Cont, ContT

    MonadCont 类型类 class Monad m => MonadCont m where callCC :: ((a -> m b) -> m a) -> m a in ...

随机推荐

  1. javascript的循环使用

    学习网址: http://www.w3school.com.cn/js/js_loop_for.asp JavaScript 循环 如果您希望一遍又一遍地运行相同的代码,并且每次的值都不同,那么使用循 ...

  2. Telnet 工具远程连接服务器

    1.启动tomcat 2. 使用telnet命令  打开CMD,输入telnet  localhost 8080 3.显示如下界面,说明已经连接成功 4. 复制如下代码到连接成功的界面 HEAD / ...

  3. 关于h5屏幕适配

    1)使用rem进行等比缩放 rem作用于非根元素时,相对于根元素字体大小:rem作用于根元素字体大小时,相对于其出初始字体大小 比如根元素(html)设置font-size=12px; 非根元素设置w ...

  4. SpringCloud使用jpa之传统方式

    不说废话,直接上代码: pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xml ...

  5. Spring AOP的注解方式实现

    spring也支持注解方式实现AOP,相对于配置文件方式,注解配置更加的轻量级,配置.修改更加方便. 1.开启AOP的注解配置方式 <!-- 开启aop属性注解 --> <aop:a ...

  6. RESTful Java client with Apache HttpClient / URL /Jersey client

    JSON example with Jersey + Jackson Jersey client examples RESTful Java client with RESTEasy client f ...

  7. ROS-PCQ基于IP的限速(总带宽上下行5M)

    /ip firewall mangle add chain=forward src-address=192.168.0.0/16 \ action=mark-connection new-connec ...

  8. [UE4]C++ 动态内存分配(6种情况,好几个例子)

    1.堆内存分配 : C/C++定义了4个内存区间: 代码区,全局变量与静态变量区,局部变量区即栈区,动态存储区,即堆(heap)区或自由存储区(free store). 堆的概念: 通常定义变量(或对 ...

  9. nodejs基础: 如何升级Noejs版本

    Node.js的开发非常活跃,它的最新稳定版本也频繁变化,你不时会发现,一个模块不能在你当前的Node版本上使用,此时你需要升级Node 幸运的是,可以用一种非常简单的方法来管理你的Node版本,即使 ...

  10. 最近比赛中遇到的几道dp题

    1.2015 icpc 长春-H-Partial Tree(据说是完全背包,但我觉得不像) 一.题意 给定$n$个点,每一个点$i$的权值为关于度数$d_i$的函数$f(d_i),$让你构建一棵树,使 ...