Zygomorphism
>はい、 foldr
の強化版として paramorphism
(または para
)があります。 para
は、現在の要素とその要素のリストの残りの部分を同時に考慮することができる特性を持っています。
> 同様に、foldlの強化版として zygomorphism
(または zygo
)があります。 zygomorphism
は、 foldl
の動作を模倣しながら、途中の計算結果を保持しておく能力を持っています。これにより、リストの左側から右側に向かって処理を行いながら、途中の計算結果にアクセスすることができます。
> しかし、 zygomorphism
は foldl
の直接的な強化版というわけではなく、 foldl
とは異なる特性を持っています。 zygo
は、2つの畳み込み関数を同時に使用することで、一方の関数の結果をもう一方の関数にフィードバックする能力を持っています。
> 簡単に言えば、 para
は foldr
の強化版として、リストの右側から左側に向かって処理を行う能力を持っています。一方、 zygo
は、リストの左側から右側に向かって処理を行いながら、途中の計算結果にアクセスする能力を持っています。
hszygo :: (b -> a -> b) -> (b -> a -> a) -> b -> [a] -> a
zygo f g acc [] = acc
zygo f g acc (x:xs) = g (f acc x) x (zygo f g (f acc x) xs)
思ってたのとけっこう見た目が違った

paraは追加の値を持っているけど、zygoは追加の関数を持ってるんだ
追加の関数 f
がタプルを返せば、para同様に追加の値を持てるのか↓
>以下は、 zygo
を使用してリストの要素の合計とその平均を計算する例です。
> 合計と平均を計算するための補助関数と主要関数を定義します:
hs-- 補助関数: 合計を計算する
sumAux :: (Int, Int) -> Int -> (Int, Int)
sumAux (sum, count) x = (sum + x, count + 1)
-- 主要関数: 平均を計算する
averageMain :: (Int, Int) -> Int -> (Int, Int) -> Double
averageMain (sum, count) _ _ = fromIntegral sum / fromIntegral count
sumAux
の定義が恣意的すぎる感じもする

再利用性がほぼない
> 最後に、 zygo
を使用して平均を計算する関数を定義します:
hsaverage :: [Int] -> Double
average xs = zygo sumAux averageMain (0, 0) xs
> この average
関数を使用すると、リストの要素の平均を計算することができます。例えば:
hsmain :: IO ()
main = do
print $ average [1, 2, 3, 4, 5] -- 3.0
> この例では、 zygo
はリストの要素の合計とその要素数を計算するための補助関数 sumAux
と、その結果を使用して平均を計算する主要関数 averageMain
を使用しています。
hszygo :: Functor f => (f b -> b) -> (f (a, b) -> a) -> Fix f -> a
zygo f g = fst . cata (\x -> (g x, f (fmap snd x)))