3

リストのn番目の要素を複製したいのですが、haskellに関する知識は非常に限られています。リストを2つの部分に分割してから、最初の部分の最後の要素を取得して、それらの部分の間に貼り付けてみました。

dupl n (x:xs) = (take n (x:xs)) ++ ( (x:xs) !! n) ++ (drop n (x:xs))

しかし、私は常にエラーが発生します:

Prelude> :l f.hs
[1 of 1] Compiling Main             ( f.hs, interpreted )

f.hs:5:39:
   Occurs check: cannot construct the infinite type: a0 = [a0]
   In the first argument of `(:)', namely `x'
   In the first argument of `(!!)', namely `(x : xs)'
   In the first argument of `(++)', namely `((x : xs) !! n)'
Failed, modules loaded: none.

誰かが私が間違っていることを教えてもらえますか?

4

3 に答える 3

4

list !! nリストではなく、リスト要素を返します。リスト++のみを連結できます; を使用してリスト要素をリストに追加することはできません。++

より正式に言えば!!、次のタイプがあります。

(!!) :: [a] -> Int -> a

aこれは、 sとanのリストを受け入れ、 。Intを返すことを意味しますa++一方、次のタイプがあります。

(++) :: [a] -> [a] -> [a]

これは、sの2つのリストを受け入れ、asの新しいリストを返すことを意味しますa。つまり、++はリストを受け入れますが、リストを!!返さないことがわかります。したがって、そのようにリストをチェーンすることは許可されていません。


これをどのように修正しますか?list !! nタイプチェッカーがヒッシーフィットをスローせずに要素を他の2つのリストに連結するには、要素をリストに入れる必要があります。

これでうまくいくはずです:

dupl n l = (take n l) ++ [l !! n] ++ (drop n l)

同様に、選択した要素を右側のリストに追加し、それを元のリストの残りの半分に連結します。

dupl n l = (take n l) ++ ((l !! n):(drop n l))

警告レクター:@Marimuthuの提案とは異なり、上記の関数は両方とも、がn範囲外のインデックスである場合に例外を発生させます。例外はから来!!ます。

于 2013-02-25T23:26:48.537 に答える
2

悪いインデックスを選択した場合は、エンプターに警告しますが、— </ p>

dupN n xs = let (first, x:rest) = splitAt (n-1) xs in first ++ x:x:rest
于 2013-02-26T00:55:21.757 に答える
1

splitAtを使用することもできます:

dupl n xs = first ++ take 1 rest ++ rest where (first, rest) = splitAt (n - 1) xs 

nが範囲外の場合、これは壊れません。

于 2013-02-26T00:06:22.433 に答える