これはミハイルさんとuser2297560さんの回答に余談です。
トラッキング機能を追加するために関数をゼロから書き直すのではなく、元の実装を何らかの形で再利用することができますか?
我々は
- はモナドが、モナド上の多型であることの基本機能を書くことができます。
fix
の助けを借りて、匿名再帰を使用して定義されます。たとえば、
:
import Data.Function(fix)
import Data.Functor.Identity
maximumAux :: (Monad m,Ord a)
=> ([a] -> m a)
-> [a] -> m a
maximumAux _ [] = error "maximum of empty list"
maximumAux _ [x] = return x
maximumAux recurse (x:xs) =
do maxTail <- recurse xs
return (max x maxTail)
maximumPure :: Ord a => [a] -> a
maximumPure as = runIdentity (fix maximumAux as)
そして、このような楽器を、オリジナルのロジックの再利用:
maximumInstrumented :: (Ord a, Show a) => [a] -> IO a
maximumInstrumented = fix (instrument maximumAux)
where
instrument auxf iorecurse as =
do print $ "starting call with params " ++ show as
a <- auxf iorecurse as
print $ "ending call with value" ++ show a
return a
しかし、「デフォルトでモナドは」あまりにも実用的ではないとして、おそらく関数を定義します。
これは最も便利なことではありませんが、現在の再帰深度を保存し、 '(actualResult、finalRecursionDepth)'を返すために、関数を変更して余分な引数を取ることができます。 – Michail
これは実際に私が必要としているものです。あなたは精巧にお聞かせください。 @Michail –
私は答えを書いた。たとえコメントの長さが許せばコメントに置くには大きすぎます。 – Michail