广义的“折叠”或如何一次执行“折叠”和“映射”



(按标题道歉,我做得再好不过了)

我的问题是找到一些通用的结构或"标准"函数来执行下一件事:

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

然后,我们不仅可以映射元素,还可以映射整个结构。

一些(非真实的)示例

xmap id myBinaryTree :: [a]

现在,我必须做一个显式结构转换器(典型的fromListtoList),然后是

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

(为了执行toStructfromStruct,我使用fold)。

是否存在推广to/from结构的方法?(应该是)是否存在该函数(xmap)?

谢谢!!:)

由于fg是函子,自然变换就是您要寻找的(另请参阅您可以定义自然变换)。所以像这样的转变

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

需要创建xmap,然后它就只是

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

您仍然需要定义(f :~> g)的类型,但没有通用的方法。

我想补充一下tel的答案(我是在阅读后才知道的),在许多情况下,你可以进行与foldMap类似的一般自然变换。如果我们可以使用foldMap,我们就知道f就是Foldable。然后我们需要一些方法来构造CCD_ 16的元素并将它们组合在一起。我们可以使用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

然后使用tel的xmap

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

我们可以做这样的事情

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

最新更新