triple2.hs (以下) をコンパイルすると、 bunnyc: qname not found: "a" となる。
main = let (a, b, c) = (1, 2, 3) in print a
なお、print a を print "foo" などにかえて、a を参照しないようにすると、今度はランタイムエラーとなる。
memo:
pair なら問題なし:
main = let (a, b) = (1, 2) in print (a+b)
タプルに限らず、3つ以上の引数をとるパターンがだめみたい。たとえば、つぎのような:
data Triple a b c = Triple a b c
main = let Triple a b c = Triple 1 2 3
in print a
Pair a b だと OK だった。これで被疑箇所はかなり絞れると思う。 これを対処したときには、同様のパターンで複数の引数をとるパターンをざーーっと試験しよう。こんなの(これを16引数くらいまではやろう):
data X a b c d = X a b c d
main = let X a b c d = X 1 2 3 4
in print d
犯人は、ここ(Rename.hs の一部):
trAsPat n (A.FunAppExp (A.FunAppExp c a) b) rhs = do
let d1 = [A.ValDecl (A.VarExp n) rhs]
a1 = A.VarExp (Name "_a#1" (0,0) False)
a2 = A.VarExp (Name "_a#2" (0,0) False)
cab = A.FunAppExp (A.FunAppExp c a1) a2
e2 = A.CaseExp (A.VarExp n) [A.Match cab (A.UnguardedRhs a1 [])]
e3 = A.CaseExp (A.VarExp n) [A.Match cab (A.UnguardedRhs a2 [])]
d2 = case a of
A.WildcardPat -> []
_ -> [A.ValDecl a (A.UnguardedRhs e2 [])]
d3 = case b of
A.WildcardPat -> []
_ -> [A.ValDecl b (A.UnguardedRhs e3 [])]
in return $ concat [d1, d2, d3]
この場合、いつも最後の2変数のみ束縛できちゃうんだな。実際、つぎのようなプログラムは現状でも動作する:
main = let (a, b, c) = (1, 2, 3) in print c
ちなみに、let [a, b, c] = [1, 2, 3] みたいなケースは、 let (a : ( b : (c : []))) = [1, 2, 3] なので、2引数でカバーされていた (sample203.hs)。
以下のように修正:
- trAsPat n (A.FunAppExp (A.FunAppExp c a) b) rhs = do
- let d1 = [A.ValDecl (A.VarExp n) rhs]
- a1 = A.VarExp (Name "_a#1" (0,0) False)
- a2 = A.VarExp (Name "_a#2" (0,0) False)
- cab = A.FunAppExp (A.FunAppExp c a1) a2
- e2 = A.CaseExp (A.VarExp n) [A.Match cab (A.UnguardedRhs a1 [])]
- e3 = A.CaseExp (A.VarExp n) [A.Match cab (A.UnguardedRhs a2 [])]
- d2 = case a of
- A.WildcardPat -> []
- _ -> [A.ValDecl a (A.UnguardedRhs e2 [])]
- d3 = case b of
- A.WildcardPat -> []
- _ -> [A.ValDecl b (A.UnguardedRhs e3 [])]
- in return $ concat [d1, d2, d3]
+ trAsPat n e@(A.FunAppExp _ _) rhs = do
+ let parsef (A.FunAppExp f@(A.FunAppExp _ _) a) vs = parsef f (a:vs)
+ parsef (A.FunAppExp c a) vs = (c, a:vs)
+ (c, vs) = parsef e []
+ d0 = A.ValDecl (A.VarExp n) rhs
+ as = [A.VarExp (Name ("_a#" ++ show i) (0,0) False)
+ | i <- [1..(length vs)]]
+ cas = foldl' A.FunAppExp c as
+ ds = [case v of
+ A.WildcardPat -> []
+ _ -> [A.ValDecl v (A.UnguardedRhs e [])]
+ | (v, a) <- zip vs as
+ , let e = A.CaseExp (A.VarExp n) [A.Match cas (A.UnguardedRhs a [])]
+ ]
+ in return $ (d0:concat ds)
sample324, 325, 326, 327 を追加。