首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >换能器与部分应用的功能有何不同?

换能器与部分应用的功能有何不同?
EN

Stack Overflow用户
提问于 2014-10-30 13:07:38
回答 1查看 3.4K关注 0票数 35

在阅读了关于Clojure (http://blog.podsnap.com/ducers2.html)介绍传感器的这篇文章之后,我对换能器是什么感到困惑。在Haskell中部分应用的map (如map (+1) )是否是换能器?起初,我认为这是使用部分应用程序的Clojure方式,但随后本文继续使用显式类型在Haskell中实现它。它在Haskell有什么用?

EN

Stack Overflow用户

回答已采纳

发布于 2014-10-30 22:05:46

在Clojure中,(map inc)是一个转换器,但不是在Haskell中,因为Haskell必须服从运行,但是一个非类型化的Lisp可以打破默认的咖喱惯例。相反,换能器的类型是:

代码语言:javascript
复制
type Transducer a b = forall r . (b -> r -> r) -> (a -> r -> r)

我们说换能器‘把a变成b’。是的,ab在右边看起来是“向后”的。forall意味着转换器必须将r保留为通用类型变量,但完全允许专门处理ab

让我倒转其中的两个论点:

代码语言:javascript
复制
-- cf. with foldr :: (x -> r -> r) -> r -> [x] -> r
ffoldr :: (x -> r -> r) -> [x] -> r -> r
ffoldr = flip . foldr

(我们也可以使用foldl,但它以后可能会逆转)。这意味着可以使用Transducerffoldr的第一个参数从x转换为y,这样我们就可以使用foldr处理带有y -> r -> r[x]。换能器位于输入([x], r)和最终处理器(y, r) -> r之间。

我已经翻转了第二个论点,以强调,令人惊讶的是,ffoldr :: Transducer [x] x。通过使用参数的对称性,我们还得到了换能器的通用组合,这恰好是函数组合:

代码语言:javascript
复制
(.) :: Transducer a b -> Transducer b c -> Transducer a c

(如果您认为给出这些forall r术语可以让我们逆转您通常使用.的方式是很酷的,那么您可以通过一种称为“延续传递”的技术任意使用。)

例如,这里是过滤器转换器:

代码语言:javascript
复制
tfilter :: (a -> Bool) -> (a -> r -> r) -> a -> r -> r 
    -- or: (a -> Bool) -> Transducer a a
tfilter predicate f a = if predicate a then f a else id

这只在谓词保持的情况下将约简函数f应用于ar。还有一个映射换能器:

代码语言:javascript
复制
tmap :: (a -> b) -> (b -> r -> r) -> a -> r -> r 
tmap ba f a = f (ba a)

这为任何“可转换”类型提供了可组合的map/filter语义:一个map/filter可以在多个上下文中工作。

Transducer类型有一个可爱的同构:结果是列表forall r. (x -> r -> r) -> r -> rforall r. (x -> r -> r) -> r -> r与列表[x]完全等价(它是列表的“教堂编码”),因此将参数a交换到换能器定义的最前面给我们(IMO更容易理解!)type TransL a b = a -> [b]型这一点更容易理解:

代码语言:javascript
复制
tl_map f = \a -> [f a]
tl_filter predicate = \a -> if predicate a then [a] else []

若要在列表中运行这些,请使用concatMap..。正好是>>=!所以你只需写collection >>= transducer,你就有了换能器集合。然后,TransL a b的意思是,“获取a原始列表中的每个元素,并给出0或多个类型为b的元素,以便连接到我的传出列表中。”当谓词不工作时,它通过剪接0元素来过滤;它通过为每个输入元素生成1个输出元素来映射;另一个操作tl_dupe = \a -> [a, a]是一个转换器,它复制列表中的元素,[1,2,3] >>= tl_dupe变成[1,1,2,2,3,3]

foldr看起来是一个Transducer [x] x时,它现在被认为与id :: TransL [x] x完全相同,它可以简单地在计算过程中执行concat操作;这个代数中的恒等函数实际上是return = \a -> [a],也是写好的(:[])唯一的损失是我们不能再使用.来组合这些,但实际上,在Control.Monad中提供了与Kleisli复合运算符>=>相同的组合。

长话短说,换能器是函数,a -> [b]巧妙地转换了一些教堂编码,使得清单单箭头的Kleisli组合运算符变成了简单的(.)

票数 46
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26653829

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档