0

以下の関数で高調波級数を計算しようとしています。しかし、型エラーがあり、それが何を意味するのかよくわかりませんか? 別の質問ですが、[5..1] で空のリストが返されるのはなぜですか?

sumHR = フォルダー (+) 0 (\x -> マップ (1/) [1..x])

エラーメッセージ:

*** Expression     : foldr (+) 0 (\x -> map (1 /) (enumFromTo x 1))
*** Term           : \x -> map (1 /) (enumFromTo x 1)    
*** Type           : b -> [b]    
*** Does not match : [a]    
4

3 に答える 3

7

このエラーは、コードが適切に型付けされておらず、意味がないことを示しています。

あなたの機能:

sumHR = foldr (+) 0 (\x -> map (1/) [1..x])

検討:

Prelude> :t foldr
foldr :: (a -> b -> b) -> b -> [a] -> b

したがって、これが真であるために(+)は、 が最初の引数であり、型を統一する (a -> b -> bおよび にNum a => a -> a -> a統一するNum a => a -> a -> a) 必要があります。

2 番目の引数には variable 型が指定されますがb、これは既に である必要があることがわかっていますNum a => a。これで問題ありません0。2 番目の引数として指定しました。

3 番目の引数は type と一致する必要がありNum a => [a]ます。ただし、関数である 2 番目の引数を指定しました。

Prelude> :t (\x -> map (1/) [1..x])
(\x -> map (1/) [1..x]) :: (Enum b, Fractional b) => b -> [b]

(Enum b, Fractional b) => b -> [b]の型を同じにする方法をコンパイラに示すことができない限りNum a => [a]、あなたは立ち往生しています。

次のような関数を使用している可能性があります。

sumHR x = foldr (+) 0 (map (1/) [1..x])
于 2013-05-14T01:54:48.833 に答える
4

無意味に書こうとしてたの?その場合は、合成演算子を使用して で合成する必要が.ありfoldr (+) 0ます(\x -> map (1/) [1..x])

sumHR = foldr (+) 0 . (\x -> map (1/) [1..x])

または、要点:

sumHR x = foldr (+) 0 (map (1/) [1..x])

(ちなみに、効率のためfoldl'に の代わりに使用したいでしょうfoldr

于 2013-05-14T01:54:09.907 に答える
4

以前の回答では、明らかに必要な署名で関数を修正する方法を説明しました。ただし、要求する各要素を最初から開始する必要があるため、これはシーケンスを計算するための実際には良い方法ではありません。はるかに効率的で、Haskell では実際に簡単なアプローチは、シーケンス全体を表す 1 つの遅延リストを計算することです。だから、あなたはから始めます

map (1/) [1..]

(または、おそらくもっと読みやすい[ 1/i | i<-[1..] ])、「結果の各要素は、指定されたリスト内の先行するすべての要素の合計です」を実行します。これをスキャンと呼びます。これはリストの片側全体で常に厳密であるため (折り畳みのように 2 つの要素だけではなく)、左側から行う必要があります。あなたは書ける

sumHR' :: Fractional x => [x]
sumHR' = scanl (+) 0 [ 1/i | i<-[1..] ]

または、同様に、無限リストは決して空ではないため、

sumHR' = scanl1 (+) [ 1/i | i<-[1..] ]
于 2013-05-14T08:03:57.523 に答える