[英]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.