5

(按标题道歉,我不能做得更好)

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

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)?

谢谢!!:)

4

2 回答 2

5

f和仿函数一样g自然变换就是您要寻找的(另请参阅您可以定义自然变换)。所以像这样的转变

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),但没有通用的方法。

于 2013-07-24T18:00:24.460 回答
4

我想补充一下tel 的答案(我是在阅读后才知道的),在许多情况下,您可以进行与foldMap. 如果我们可以使用foldMap,我们就知道fFoldable。然后我们需要一些方法来构造元素g a并将它们组合在一起。我们可以使用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

然后使用电话xmap

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

我们可以做类似的事情

> xmap (+1) nt (Just 1) :: [Int]
[2]
于 2013-07-24T19:58:07.220 回答