2017-03-03 7 views
3

再帰呼び出しチェーンで情報を後方に伝播する方法はありますか。例えば再帰呼び出しで情報を後方に伝播する

f :: [Int] -> [Int] 
f (x:xs) 
    | x `mod` 17 = ... 
    | otherwise = (x + 1) : f xs 
f [] = [] 

私は...での評価を停止したい、と私はまた戻って、発信者(それが停止したという事実)にその情報を伝播します。私はMaybeのような戻り値型を使用しようとしましたが、再帰呼び出しのパターンマッチングを行う必要があったため、呼び出し後に評価しなければならなかったので、テールコール最適化が失われました(注: TR形式ですが、わかりやすいようにこのように残しました)。

さらに優れたソリューションを試しても、TCOのメリットはありますか?

+0

これはもう問題ではないので、この質問を議論の対象にしないように投票しています(OPはそれを理解しました) – luqui

+5

ハスケルでの保護された再帰よりもテールの再帰はあまり重要ではありません。 https://wiki.haskell.org/Tail_recursion – chepner

+0

関連項目:* Haskellにテール再帰的な最適化がありますか?*](http://stackoverflow.com/q/13042353/2751851) – duplode

答えて

3

追加のパラメータを使用して、累積結果を含むタプルを返すことができます。この方法でもTCOの恩恵を受け、必要な情報を得ることができます。

例:

f :: [Int] -> Bool -> [Int] -> (Bool, [Int]) 
f (x:xs) l accum 
    | x `mod` 17 == 0 = (False, accum) 
    | otherwise  = f xs l ((x+1) : accum) 
f [] l accum = (True, accum) 

以上の洗練された方法で

data CheckedValue a = Valid a | Invalid a 
    deriving Show 

f :: [Int] -> [Int] -> CheckedValue [Int] 
f (x:xs) accum 
    | x `mod` 17 == 0 = Invalid accum 
    | otherwise  = f xs ((x+1) : accum) 
f [] accum = Valid accum 

注:これらの関数は、リストを逆に、それに注意を払っていません。

関連する問題