

今Haskellを使ってタイトルでも書いたように毎ｎ番目の数字をリストから消すコードを書いているのですがどうもうまくいきません。

例）

[code]

    dropevery [0,1,2,3,4,5,6,7,8,9] 3
    [0,1,3,4,6,7,9] 
    
[/code]

*2, 5, 8 と毎3番目の数字がリストから落とされ残った数字が表示されるコードです。

いま色々試しているのですがなかなかうまくいきません。  
以下のコードは色々試して、いろいろなサイト等をみて書いたものです。まだコーディングが必要な箇所もあるのですが、何を書いたらいいのか分からないです（？と記入した箇所）

どなたか解決案がある方がいらしたら、答えていただけると幸いです。また訂正箇所もあったら教えていただけると幸いです。  
よろしくお願いします。

現在のコード

[code]

    dropevery :: [a] -> Int -> [a]
    dropevery [] _ = []
    dropevery xs n = go 0 xs
        where go _ [] = []
              go i (y:ys) | i == n = 0（？）
                          | otherwise = ？
                                                                        
    main = putStrLn (show (dropevery)[0,1,2,3,4,5,6,7,8,9] 3)
    
[/code]


CC BY-SA 4.0
2022-10-07T00:29:24.540
91472
2022-10-07T07:09:31.447
2022-10-07T00:41:02.740
3060
54742
question
haskell
毎ｎ番目の数字をリストから消したい


こちらでいかがでしょうか:

[code]

    dropevery :: [a] -> Int -> [a]
    dropevery xs n = go xs
     where
      go xs' =
        let (xsNotDropped, xsLeft) = splitAt (n - 1) xs'
         in
          case xsLeft of
              [] -> xsNotDropped
              (_ : xsAfterN) ->
                xsNotDropped ++ go xsAfterN
    
    
    main = putStrLn (show (dropevery [0,1,2,3,4,5,6,7,8,9] 3))
    
[/code]

以下補足事項:

  * もし勉強のために敢えてやっているのであれば恐縮ですが、こういうときは極力自分では再帰を書かずに、標準ライブラリーにある関数（上記の場合`splitAt`）を利用するのをお勧めします。
  * 一般にHaskell製の関数は、他の多くのプログラミング言語と異なり、「主に処理する引数」を後ろに置くことが推奨されています。その方がカリー化と相性がいいためです（詳細が気になる場合は追加の質問を！）。なのでどちらかというと、`dropevery :: Int -> [a] -> [a]`という型にした方がいいかと思います。


CC BY-SA 4.0
2022-10-07T03:52:10.960
91476
2022-10-07T03:52:10.960
8007
91472
answer


先頭のn要素を落した部分に対して当該の計算ができたら、それを先頭の(n-1)要素のリストにアペンドすればよい、という最後の一歩に気づけば、シンプルに以下のように考えることができます．

(1) 先頭から(n-1)個もぎとる  
(2) 残りの先頭を捨てる  
(3) その残りに dropEvery n を適用  
(4) (1)と(3)を連結

[code]

    dropEvery :: Int -> [a] -> [a]
    dropEvery _ [] = []
    dropEvery n xs = take (n-1) xs ++ dropEvery n (drop n xs)
    
[/code]

また、  
(1)先頭から(n-1)個もぎ取る  
(2)残りの先頭を捨てる  
の部分を繰り返して、先に長さn-1以下のリストのリストを得て、これを concat で連結するという方法もあります.  
「つきたて餅から少しずつ捻り取って丸めて黄粉をまぶして、黄粉もちをたくさんつくる」のような（個人の感想）この手法は、unfoldr :: (a ->
Maybe (b, a)) -> a -> [b]（Data.Listモジュールにあります）という標準関数で抽象化されています．

[code]

    dropEvery :: Int -> [a] -> [a]
    dropEvery n = concat . unfoldr f
        where
            f [] = Nothing
            f xs = Just (take (n-1) xs, drop n xs)
    
[/code]


CC BY-SA 4.0
2022-10-07T07:09:31.447
91482
2022-10-07T07:09:31.447
24701
91472
answer