(按标题道歉,我做得再好不过了)
我的问题是找到一些通用的结构或"标准"函数来执行下一件事:
xmap :: (a -> b) -> f a -> g b
然后,我们不仅可以映射元素,还可以映射整个结构。
一些(非真实的)示例
xmap id myBinaryTree :: [a]
现在,我必须做一个显式结构转换器(典型的fromList
,toList
),然后是
toList . fmap id -- if source struct has map
fmap id . fromList -- if destination struct has map
(为了执行toStruct
、fromStruct
,我使用fold
)。
是否存在推广to
/from
结构的方法?(应该是)是否存在该函数(xmap
)?
谢谢!!:)
由于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)
的类型,但没有通用的方法。
我想补充一下tel的答案(我是在阅读后才知道的),在许多情况下,你可以进行与foldMap
类似的一般自然变换。如果我们可以使用foldMap
,我们就知道f
就是Foldable
。然后我们需要一些方法来构造CCD_ 16的元素并将它们组合在一起。我们可以使用Alternative
,它拥有我们所需要的一切(pure
、empty
和<|>
),尽管我们也可以为此构建一些不太通用的类型类(我们在任何地方都不需要<*>
)。
{-# 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]