11

次のスニペットでは、Haskellで書いた2つのコラッツ関数を見ることができます。再帰的なアプリケーションでは、最初の例(collat​​z)で括弧を使用して、正しい優先順位を取得しました。

$で関数適用を学んだばかりなので、それを使って関数(collat​​z')を書き直そうとしました。ただし、次のエラーが発生します。

期待されるタイプ`[a]'を推測されるタイプ`a1->[a1]'と一致させることができませんでした`(:)'の2番目の引数、つまり` collat​​z'' `($)'の最初の引数、つまり`n:コラッツ''式の中で:n:コラッツ'$ n` div` 2

collatz :: (Integral a) => a -> [a]

collatz 1 = [1]

collatz n | even n    = n : collatz (n `div` 2)
          | otherwise = n : collatz (n * 3 + 1)

collatz' :: (Integral a) => a -> [a]

collatz' 1 = [1]

collatz' n | even n    = n : collatz' $ n `div` 2
           | otherwise = n : collatz' $ n * 3 + 1

これがうまくいかなかったのは私には奇妙なことになりました。だから私はうまくいった同様の例を試しました:

True : [even $ 3 `div` 3]

誰かがそれを見て、私が間違っていることを教えてくれたら、私はそれを感謝します。

4

4 に答える 4

18

$:優先順位が(およびその他の)よりも低いため、関数は次のように解析されます。

(n : collatz') $ (n `div` 2)

これにより、タイプエラーが発生します。の2番目の引数は:リストを期待していますが、代わりにコラッツ関数を渡しています。

それでも3n+1の部分の括弧を避けたい場合は、次のようにすることができます。

(n:) . collatz' $ n `div` 2
n : (collatz' $ n `div` 2)

これらは必ずしもオリジナルよりもきれいではありませんが。ご参考までに(n:)、最初の例では、\x -> n : x

于 2011-12-04T21:20:19.013 に答える
10

他の人が問題が何であるかを説明しているので、私はあなたが自分でこれを理解することができた方法を説明すると思いました。(男に魚を教えるなど...)

エラーメッセージのこの部分に注意してください。

'($)'の最初の引数、つまり' n:collat​​z''

これが優先順位の問題であることに気付くための手がかりです。GHCは、最初の引数がちょうどであると期待していたのに対し、それはn : collatz'の最初の引数として解析されたと言っています。$collatz'

この時点で、私は通常GHCiを起動し、次の:infoコマンドを使用して関連する優先順位を確認します。

> :info :
data [] a = ... | a : [a]   -- Defined in GHC.Types
infixr 5 :
> :info $
($) :: (a -> b) -> a -> b   -- Defined in GHC.Base
infixr 0 $

:の優先順位は5であり、の優先順位は0であることが示されています。これは、が。よりも「緊密に」バインド$されている理由を説明しています。:$

于 2011-12-04T22:00:43.840 に答える
6

:より強く結合します$。検討

Prelude> let f x = [x]
Prelude> 1 : f 2
[1,2]
Prelude> 1 : f $ 2

<interactive>:1:5:
    Couldn't match expected type `[a0]' with actual type `t0 -> [t0]'
    In the second argument of `(:)', namely `f'
    In the expression: 1 : f
    In the expression: 1 : f $ 2

1 : fパーサーによって検出された「式」に注意してください。では(1 : f) $ 2なく表示され1 : (f $ 2)ます。

于 2011-12-04T21:21:15.927 に答える
3

@missingnoが述べたように、これは演算子の優先順位の問題です。このように書き直すことができます

collatz' n | even n    = n : (collatz' $ n `div` 2)
           | otherwise = n : (collatz' $ n * 3 + 1)

しかし、まだ括弧が付いているので、それは明らかにあなたをあまり購入しません。

于 2011-12-04T21:23:38.277 に答える