2016-09-11 2 views
6

私は固定小数点と再帰的定義の周りに頭を曲げようとしています。なぜhaskellの `fix`はタプルに問題があるようですか?

これは動作します:

>>> take 10 $ fix (\x -> (0:x)) 
[0,0,0,0,0,0,0,0,0,0] 

は今、私は再帰的に定義されたペアをいじり始めるとします:

>>> take 10 $ let x = (0:x) in x 
[0,0,0,0,0,0,0,0,0,0] 

これはfixの定義与えられた意味を成して同じことを、い

>>> take 10 $ fst $ let (u,v) = (0:v,1:u) in (u,v) 
[0,1,0,1,0,1,0,1,0,1] 

さて、私はでそれを書くことができるはずですも、そうですか?

>>> take 10 $ fst $ fix (\(u,v) -> (0:v,1:u)) 
*** Exception: <<loop>> 

しかし、動作しません。

>>> take 10 $ fst $ fix (\r -> let (u,v)=r in (0:v,1:u)) 
[0,1,0,1,0,1,0,1,0,1] 

最後の2つの例の重要な違いは何ですか?

答えて

14

怠惰なパターンマッチングを行うようにあなたが

take 10 $ fst $ fix (\ ~(u,v) -> (0:v,1:u)) 
         ^^^ 

をしたいです。 letでは、LHSパターンは暗黙的に遅延/反駁可能である。

普通の\(u,v) -> ...では、出力が生成される前にラムダの引数が要求されます。これにより、関数がfixに対して厳しくなりすぎます。あなたが必要とするものは、引数がラムダによって強制されないように(一致するコンストラクタはありません)、

take 10 $ fst $ fix (\p -> (0:snd p,1:fst p)) 

のようなものです。遅延パターンアプローチは、上記のfst/sndに相当します。

+1

これは '\(〜(u、v))'または '\〜(u、v)'でなければなりません。 – redneb

+3

@redneb固定。 (意図された言葉遣い:-P) – chi

関連する問題