Haskell语言学习笔记(26)Identity, IdentityT
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 bm >>= 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 bm >>= 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的更多相关文章
- Haskell语言学习笔记(88)语言扩展(1)
ExistentialQuantification {-# LANGUAGE ExistentialQuantification #-} 存在类型专用的语言扩展 Haskell语言学习笔记(73)Ex ...
- Haskell语言学习笔记(79)lambda演算
lambda演算 根据维基百科,lambda演算(英语:lambda calculus,λ-calculus)是一套从数学逻辑中发展,以变量绑定和替换的规则,来研究函数如何抽象化定义.函数如何被应用以 ...
- Haskell语言学习笔记(69)Yesod
Yesod Yesod 是一个使用 Haskell 语言的 Web 框架. 安装 Yesod 首先更新 Haskell Platform 到最新版 (Yesod 依赖的库非常多,版本不一致的话很容易安 ...
- Haskell语言学习笔记(20)IORef, STRef
IORef 一个在IO monad中使用变量的类型. 函数 参数 功能 newIORef 值 新建带初值的引用 readIORef 引用 读取引用的值 writeIORef 引用和值 设置引用的值 m ...
- Haskell语言学习笔记(39)Category
Category class Category cat where id :: cat a a (.) :: cat b c -> cat a b -> cat a c instance ...
- Haskell语言学习笔记(72)Free Monad
安装 free 包 $ cabal install free Installed free-5.0.2 Free Monad data Free f a = Pure a | Free (f (Fre ...
- Haskell语言学习笔记(44)Lens(2)
自定义 Lens 和 Isos -- Some of the examples in this chapter require a few GHC extensions: -- TemplateHas ...
- Haskell语言学习笔记(38)Lens(1)
Lens Lens是一个接近语言级别的库,使用它可以方便的读取,设置,修改一个大的数据结构中某一部分的值. view, over, set Prelude> :m +Control.Lens P ...
- Haskell语言学习笔记(30)MonadCont, Cont, ContT
MonadCont 类型类 class Monad m => MonadCont m where callCC :: ((a -> m b) -> m a) -> m a in ...
随机推荐
- 使用Angular提交表单
使用Angular提交表单 我们准备在之前使用的<script>标签中设置我们的Angular应用.所以删除里面的内容,我们就可以开始了. 设置一个Angular应用 步骤为: 1. 加载 ...
- js 正则用空格分割字符串
var filename = "ASDFK*SADF+ALDLAS-LDKFADFa*seAc tion.java";var arr = filename.split(/\*|\- ...
- 学习笔记之Moq
dotnet/src/MoqSample at master · haotang923/dotnet · GitHub https://github.com/htanghtang/dotnet/tre ...
- 安卓手机安装虚拟定位的方法Xposed安装器+模拟位置(Xposed模块)
原文:https://www.52pojie.cn/thread-571328-1-1.html 未测试,据说只支持某些手机,小米和华为很难安装,建议买其他品牌. Xposed安装器步骤:·ROOT你 ...
- CA单向认证和双向认证的区别?
1:单向认证,内容会被串改吗?
- API网关Kong系列(四)认证配置
目前根据业务需要先介绍2种认证插件:Key Authentication 及 HMAC-SHA1 认证 Key Authentication 向API添加密钥身份验证(也称为API密钥). 然后,消 ...
- 第3章 文件I/O(6)_高级文件操作:文件锁
7. 高级文件操作:文件锁 (1)文件锁分类 分类依据 类型 说明 按功能分 共享读锁 文件描述符必须读打开 一个进程上了读锁,共它进程也可以上读锁进行读取 独占写锁 文件描述符必须写打开 一个进程上 ...
- Docker集群管理(三)—— docker swarm mode基础教程
docker从1.12版(及后续版本)集成了swarmkit.可以方便的实现docker集群.它有哪些特点呢: 集成了集群功能 分散设计:manager和worker两种节点. 声明式服务模式 可伸缩 ...
- Django中间件执行流程
中间件函数是 django 框架为我们预留的函数接口, 让我们可以干预请求和应答的过程 1. 获取浏览器端的IP地址: 使用 request.META[‘REMOTE_ADDR’] 2. 使用中间件 ...
- html大小写问题
js中变量名,函数,关键字都区分大小写,如var i;和var I;是两个不同的变量. css中定义的元素名称不区分大小写的. html中,标签和标签属性统一使用小写形式,固有属性也一律使用小写,自定 ...