Control.Monad.Reader.withReader是否为Data.Functor.Contravariant.contramap?
关于
Control.Monad.Reader与Data.Functor.Contravariant的关系 核心结论
你观察到的相似性完全成立,withReader本身就是逆变函子行为的具象实现,二者的关联核心来自Reader类型不同参数位置的方差差异:
- 首先明确
Reader r a的本质是包装了函数类型r -> a,代表接收r类型的环境、返回a类型结果的计算。 - 我们日常使用的
Reader的Functor、Applicative、Monad实例,都是针对最后一个类型参数a(结果类型)的协变实例,对应函数返回值的协变特性:fmap :: (a -> b) -> Reader r a -> Reader r b的本质就是对函数返回值做映射,和普通函数的fmap逻辑完全一致。 - 当你固定
Reader的结果类型a,将其视为「以环境类型r为参数的类型构造器」(即形如\r -> Reader r a的构造器)时,这个构造器完全符合Contravariant的定义:因为函数的入参位置本身就是逆变的,对应contramap的签名(r' -> r) -> Reader r a -> Reader r' a,和你看到的withReader签名完全匹配。 - 标准库的
Control.Monad.Reader没有直接提供Contravariant实例的原因是:Haskell的类型类实例默认作用于类型构造器的最后一个参数,Reader的最后一个参数是协变的a,如果要实现针对r的逆变实例,需要用newtype翻转参数顺序,示例如下:
{-# LANGUAGE FlexibleInstances #-} import Data.Functor.Contravariant import Control.Monad.Reader newtype FlipReader a r = FlipReader (Reader r a) instance Contravariant (FlipReader a) where contramap f (FlipReader m) = FlipReader $ withReader f m
这个contramap的实现逻辑和withReader完全等价:都是先将新环境r'通过传入的转换函数映射为原有环境r,再喂给原有Reader计算得到结果。
内容的提问来源于stack exchange,提问作者senjin.hajrulahovic
相关产品推荐
相关产品推荐

