2

类型的“地图”

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 而不是使用 (*) 会怎样?

4

0 回答 0