17

私は、ErikMeijerのChannel9WebキャストからHaskellを自分自身に教えようとしているC#の人です。zipとmodを使用してリストのすべての「n」要素をスキップするという興味深いパズルに出くわしました。

every :: Int -> [a] -> [a]
every _ [] = []
every n xs = [x | (x,i) <- zip xs [1..], i `mod` n == 0]

modの使用を避けることができれば、(非常に大きなリストやストリームの場合)より効率的かもしれないと思っていました。

iの値をnと単純に比較できるように、整数の繰り返しリストを怠惰に作成することを考えました。

repeatInts :: Int -> [Int]

呼び出しが無限repeatInts 3に返されるように[1,2,3,1,2,3,1,2,3,1,2,3,..]

これを考えると、次のeveryように再定義できます。

every :: Int -> [a] -> [a]
every _ [] = []
every n xs = [x | (x,i) <- zip xs (repeatInts n), i == n]

だから私の質問は:どのように実装しrepeatIntsますか?

4

2 に答える 2

27

使用cycle

cycle :: [a] -> [a]  

cycle有限リストを循環リスト、または同等に、元のリストの無限の繰り返しに結び付けます。それは無限のリストのアイデンティティです。

repeatIntsあなたは次の観点から定義することができますcycle

*Main> let repeatInts n = cycle [1..n]
*Main> :t repeatInts
repeatInts :: (Num t, Enum t) => t -> [t]
*Main> take 10 $ repeatInts 3
[1,2,3,1,2,3,1,2,3,1]

好奇心旺盛な方のために、GHCcycle

cycle [] = errorEmptyList "cycle"
cycle xs = xs' where xs' = xs ++ xs'

純粋関数型の用語では、この奇妙な手法は結び目を結ぶこととして知られており、無限ではなく循環データ構造を作成します。

詳細については、を参照してください

于 2010-01-10T00:11:13.893 に答える
4

遅い答えですが、次のように書くこともできます:

repeatInts :: Int -> [Int]
repeatInts 0 = []
repeatInts a = [1..a] ++ repeatInts a
于 2014-05-10T12:38:38.167 に答える