简体   繁体   English

广义的“折叠”或如何一次执行“折叠”和“地图”

[英]Generalized `fold` or how to perform `fold` and `map` at a time

(Apology by the title, I can't do better) (通过标题道歉,我不能做得更好)

My question is to find some generalized struct or "standard" function to perform the next thing: 我的问题是找到一些通用的结构或“标准”函数来执行下一件事:

xmap :: (a -> b) -> f a -> g b

then, we can map not only elements, by also the entire struct. 那么,我们不仅可以映射元素,还可以映射整个结构。

Some (not real) example 一些(不是真实的)例子

xmap id myBinaryTree :: [a]

at the moment, I must to do a explicit structure conversor (typical fromList , toList ) then 目前,我必须做一个显式的结构转换(典型的fromListtoList

toList . fmap id   -- if source struct has map
fmap id . fromList -- if destination struct has map

(to perform toStruct , fromStruct I use fold ). (执行toStructfromStruct我使用fold )。

Exists some way to generalize to / from structs? 存在某种方式来推广to / from结构? (should be) Exists that function ( xmap )? (应该)存在该功能( xmap )?

Thank you!! 谢谢!! :) :)

As f and g are functors, a natural transformation is what you're looking for (see also You Could Have Defined Natural Transformations ). 由于fg是仿函数,因此您正在寻找自然变换 (另请参阅“ 您可以定义自然变换” )。 So a transformation like 所以转型就好

f :~> g = forall a. f a -> g a 

is needed to create xmap which is then just 需要创建xmap然后才是

xmap :: (a -> b) -> (f :~> g) -> (f a -> g b)
xmap f n = map f . n

You still need to define types of (f :~> g) , but there' not a general way of doing that. 你仍然需要定义(f :~> g) ,但是没有一般的方法。

I'd like to add to tel's answer (I got my idea only after reading it) that in many cases you can make general natural transformation that will work similarly to foldMap . 我想补充一下tel的答案 (我只是在阅读之后得到了我的想法),在许多情况下,你可以进行一般自然变换,它将与foldMap类似。 If we can use foldMap , we know that f is Foldable . 如果我们可以使用foldMap ,我们知道fFoldable Then we need some way how to constructs elements of ga and combine them together. 然后我们需要一些方法来构建ga元素并将它们组合在一起。 We can use Alternative for that, it has all we need ( pure , empty and <|> ), although we could also construct some less general type class for this purpose (we don't need <*> anywhere). 我们可以使用Alternative ,它有我们需要的所有( pureempty<|> ),虽然我们也可以为此目的构造一些不太通用的类型类(我们不需要<*>任何地方)。

{-# LANGUAGE TypeOperators, RankNTypes #-}
import Prelude hiding (foldr)
import Control.Applicative
import Data.Foldable

type f :~> g = forall a. f a -> g a

nt :: (Functor f, Foldable f, Alternative g) => f :~> g
nt = foldr ((<|>) . pure) empty

Then using tel's xmap 然后使用tel的xmap

xmap :: (a -> b) -> (f :~> g) -> (f a -> g b)
xmap f n = map f . n

we can do things like 我们可以做的事情

> xmap (+1) nt (Just 1) :: [Int]
[2]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM