类型的“地图”
mapIsh :: Traversable t => (a -> Either b c) -> t a -> Either b (t c)
将是一个开始。(Hayo 没有找到。)或者类型的“折叠”
foldIsh :: (b -> a -> Either l b) -> b -> t a -> Either l b
最重要的是(就我而言)是这样的:
mapAccumIsh :: (a -> b -> Either l (a, c)) -> a -> t b -> Either l (a, t c)
这可能就是您需要阅读的全部内容。但是,如果您需要更多详细信息,这里有一个具体示例:
想象一个树状结构来 mapAccum 。每个分支在评估其子代后,都会被其子代和累加器的某些功能所转换。
下面是一些工作代码,将每棵树的值添加到累加器中,并将其子标签的乘积添加到每个分支的标签中:
module Temp where
import Data.List
data Tree = Leaf Float | Branch Float [Tree] deriving (Show)
label :: Tree -> Float
label (Leaf i) = i
label (Branch i _) = i
f :: Float -> Tree -> (Float, Tree)
f i (Leaf j) = (i+j, Leaf j)
f i (Branch j ts) = (i + tf, Branch tf ts2) where
(i2, ts2) = mapAccumL f i ts
tf = j + (foldl (*) 1 $ map label ts2)
-- the problem: what if instead of (*) in the line above, we used this?
evenMult :: Float -> Float -> Either String Float
evenMult a b = case even $ round b of True -> Right $ a * b
False -> Left "that's odd"
go = f 0 $ Branch 2 [Branch 2 [Leaf 2]
,Branch 2 [Leaf 2, Leaf (-2)]]
这是返回的内容:
(-6.0,Branch (-6.0) [Branch 4.0 [Leaf 2.0]
,Branch (-2.0) [Leaf 2.0,Leaf (-2.0)]])
但是,如果我们在 foldl 中使用 evenMult 而不是使用 (*) 会怎样?