Zygomorphism
gpt-4.icon
はい、foldrの強化版としてparamorphism(またはpara)があります。paraは、現在の要素とその要素のリストの残りの部分を同時に考慮することができる特性を持っています。
同様に、foldlの強化版としてzygomorphism(またはzygo)があります。zygomorphismは、foldlの動作を模倣しながら、途中の計算結果を保持しておく能力を持っています。これにより、リストの左側から右側に向かって処理を行いながら、途中の計算結果にアクセスすることができます。 しかし、zygomorphismはfoldlの直接的な強化版というわけではなく、foldlとは異なる特性を持っています。zygoは、2つの畳み込み関数を同時に使用することで、一方の関数の結果をもう一方の関数にフィードバックする能力を持っています。
簡単に言えば、paraはfoldrの強化版として、リストの右側から左側に向かって処理を行う能力を持っています。一方、zygoは、リストの左側から右側に向かって処理を行いながら、途中の計算結果にアクセスする能力を持っています。
code:hs
zygo :: (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)
思ってたのとけっこう見た目が違ったmrsekut.icon
paraは追加の値を持っているけど、zygoは追加の関数を持ってるんだ
追加の関数fがタプルを返せば、para同様に追加の値を持てるのか↓
GPT-4.icon
以下は、zygoを使用してリストの要素の合計とその平均を計算する例です。
合計と平均を計算するための補助関数と主要関数を定義します:
code: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の定義が恣意的すぎる感じもするmrsekut.icon
再利用性がほぼない
最後に、zygoを使用して平均を計算する関数を定義します:
code:hs
average xs = zygo sumAux averageMain (0, 0) xs
このaverage関数を使用すると、リストの要素の平均を計算することができます。例えば:
code:hs
main :: IO ()
main = do
この例では、zygoはリストの要素の合計とその要素数を計算するための補助関数sumAuxと、その結果を使用して平均を計算する主要関数averageMainを使用しています。
code:hs
zygo :: Functor f => (f b -> b) -> (f (a, b) -> a) -> Fix f -> a
zygo f g = fst . cata (\x -> (g x, f (fmap snd x)))