Ruby と抽象構文木

PEG を作ってて思ったこと。

HaskellOCaml に比べて、Ruby は抽象構文木を扱うのがすごく苦手だと思います。一つの大きな理由はパターンマッチがないことですが、それだけでは無いような気がします。

Haskell の場合、

-- 抽象構文木を定義する
data AST = Foo AST | Bar AST | Baz

-- 処理 1
foo (Foo x) = ...
foo (Bar x) = ...
foo Baz = ...

-- 処理 2
bar (Foo x) = ...
bar (Bar x) = ...
bar Baz = ...

-- 処理 3
bar (Foo x) = ...
bar (Bar x) = ...
bar Baz = ...

と言うように処理を同じ箇所にまとめて書けますが、Ruby の場合

# 抽象構文木を定義する
class AST; end
class Foo < AST
    def initialize(ast); @ast = ast; end
    # 処理 1
    def foo; ...; end
    # 処理 2
    def bar; ...; end
    # 処理 3
    def baz; ...; end
end
class Bar < AST
    def initialize(ast); @ast = ast; end
    # 処理 1
    def foo; ...; end
    # 処理 2
    def bar; ...; end
    # 処理 3
    def baz; ...; end
end
class Baz < AST
    # 処理 1
    def foo; ...; end
    # 処理 2
    def bar; ...; end
    # 処理 3
    def baz; ...; end
end

というように各処理が分散してしまいます。open class を使って

# 抽象構文木を定義する
class AST; end

class Foo < AST
    def initialize(ast); @ast = ast; end
end
class Bar < AST
    def initialize(ast); @ast = ast; end
end
class Baz < AST; end

# 処理 1
class Foo
    def foo; ...; end
end
class Bar
    def foo; ...; end
end
class Baz
    def foo; ...; end
end

# 処理 2
class Foo
    def bar; ...; end
end
class Bar
    def bar; ...; end
end
class Baz
    def bar; ...; end
end

# 処理 3
class Foo
    def baz; ...; end
end
class Bar
    def baz; ...; end
end
class Baz
    def baz; ...; end
end

と書けば、各処理は一カ所にまとまっていますが、冗長すぎて人間が書ける域を超えています。

何かいい方法はないでしょうか。