[英]Generalized `fold` or how to perform `fold` and `map` at a time
(通过标题道歉,我不能做得更好)
我的问题是找到一些通用的结构或“标准”函数来执行下一件事:
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
。 然后我们需要一些方法来构建ga
元素并将它们组合在一起。 我们可以使用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]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.