4

次の例で、再帰の代わりにリスト内包表記を使用できるかどうか知りたいです。

replaceFirst要素とリストを取り込んで、リストから最初に出現する要素を置き換える関数。

これは、次のように再帰を使用して実行できます。

replaceFirst _ [] = []
replaceFirst elem y (x:xs) | x==y = (elem:xs)
                           | otherwise = x:replaceFirst elem y xs

私の質問は、この再帰関数、またはリスト内の要素の最初の出現に作用する同様の再帰関数を、リスト内包関数に置き換えることができるかどうかです。なぜまたはなぜそうではないのですか?(私は実際のコードよりも推論に関心があります)。

4

2 に答える 2

8

リスト内包表記は、、、およびのさまざまな形式の構文糖衣です。再帰関数をこれらの観点から説明できる場合は、リスト内包に書き換えることができます。上記のように短絡することも、蓄積状態を通過することもできません。mapfilter,concatMap

replaceFirstリスト内の後の要素に前の要素の外観を「伝える」には、アキュムレータが必要なようです。これにより、リスト内包表記のみを使用して書くことが困難または不可能になると思います。

于 2013-02-24T20:54:32.610 に答える
0

leftaroundaboutに触発されたリスト内包表記:

replaceFirst elem y xs = [a | let b = break (==y) xs
                                  c = if not (null $ snd b) 
                                         then fst b ++ [elem] ++ tail (snd b) 
                                         else fst b
                              , a <- c]
于 2013-02-25T01:25:55.900 に答える