Python には、Haskell のような「データ コンストラクター」の概念がありません。他のほとんどの OOP 言語と同様に、クラスを作成できます。別の方法として、常にビルトインでデータ型を表現し、それらを処理する関数のみを定義することもできます (これは、heapq
ビルトイン モジュールでヒープを実装するために使用されるアプローチです)。
Python と Haskell の違いは非常に大きいため、Haskell と Python の構文/機能を厳密に比較することは避けたほうがよいでしょう。そうしないと、非 Pythonic で非効率的な Python コードを作成することになります。
Python に関数型の機能がいくつかあるとしても、それは関数型言語ではないため、プログラムのパラダイムを完全に変更して、読みやすく、pythonic で効率的なプログラムを取得する必要があります。
クラスを使用した可能な実装は次のとおりです。
class Bint(object):
def __init__(self, value, left=None, right=None):
self.a = value
self.left = left
self.right = right
def height(self):
left_height = self.left.height() if self.left else 0
right_height = self.right.height() if self.right else 0
return 1 + max(left_height, right_height)
def count(self):
left_count = self.left.count() if self.left else 0
right_height = self.right.count() if self.right else 0
return 1 + left_count + right_count
と の「よりスマートな」デフォルト値を提供することで、コードを少し簡略化できleft
ますright
。
class Nil(object):
def height(self):
return 0
count = height
nil = Nil()
class Bint(object):
def __init__(self, value, left=nil, right=nil):
self.value = value
self.left = left
self.right = right
def height(self):
return 1 + max(self.left.height(), self.right.height())
def count(self):
return 1 + self.left.count() + self.right.count()
これらの実装では、子を 1 つだけ持つノードが許可されることに注意してください。
ただし、クラスを使用してデータ型を定義する必要はありません。たとえば、Bint
a は単一の要素のリスト、ルートの値、または値、左の子、右の子の 3 つの要素を持つリストであると言えます。
この場合、関数を次のように定義できます。
def height(bint):
if len(bint) == 1:
return 1
return 1 + max(height(bint[1]), height(bint[2]))
def count(bint):
if len(bint) == 1:
return 1 + count(bint[1]) + count(bint[2])
さらに別のアプローチは、namedtuple
s を使用することです。
from collections import namedtuple
Leaf = namedtuple('Leaf', 'value')
Branch = namedtuple('Branch', 'value left right')
def height(bint):
if len(bint) == 1: # or isinstance(bint, Leaf)
return 1
return 1 + max(height(bint.left), height(bint.right))
def count(bint):
if len(bint) == 1: # or isinstance(bint, Leaf)
return 1 + count(bint.left) + count(bint.right)