6

それ自体に count 回追加されたリストを返す Haskell 関数を作成したいと思います ( lst * countPython のように)。

私の最初の試みは:

self_append_n :: Int -> [a] -> [a]
self_append_n = concat . replicate

私の推論はreplicate、カウントと値を受け入れ、値のリストを生成するというものです。値自体がリストの場合は、リストを連結するだけです。ただし、これにより当惑するエラーが発生します。

Couldn't match type `[a0]' with `[a] -> [a]'
Expected type: [[a0]] -> [a] -> [a]
  Actual type: [[a0]] -> [a0]
In the first argument of `(.)', namely `concat'
In the expression: concat . replicate
In an equation for `self_append_n':
    self_append_n = concat . replicate

それから私は意味のあるバージョンを書きました:

self_append_n a b = concat $ replicate a b

そしてそれは動作します!

ポイントのないバージョンがコンパイルに失敗するのに、ポイントを追加すると機能するのはなぜですか?

4

1 に答える 1

11

署名を明示的に括弧で囲むと、おそらく役立つでしょう。

selfAppend :: Int -> ([a]         -> [a])
replicate  :: Int -> ([a]->[[a]])
concat     ::          [[a]]      -> [a]

を作成しようとするとconcat . replicateconcatの部分的に適用された結果replicate、つまりが得られ[a] -> [[a]]ます。とは統一しません[[a]]

あなたがする必要があるのは、結果を渡す前に最初に両方の引数をreplicate渡すことです。それを行うためのIMOの最良の方法は、「セミポイントフリー」です。

selfAppend n = concat . replicate n

読みにくい代替手段は次のようになります

selfAppend' = curry $ concat . uncurry replicate
selfAppend'' = (concat.) . replicate

または悪名高いオペレーターと

(.:) :: (c->d) -> (a->b->c) -> a->b->d
(.:) = (.).(.)
 -- `≡ fmap fmap fmap`, also a popular implementation...

あなたは単に書くことができます

selfAppend''' = concat .: replicate
于 2014-08-31T20:45:59.603 に答える