views:

91

answers:

3

For anyone who's spent some time with sml, ocaml, haskell, etc. when you go back to using C, Python, Java, etc. you start to notice things you never knew were missing. I'm doing some stuff in Python and I realized what I really want is a functional-style datatype like (for example)

datatype phoneme = Vowel of string | Consonant of voice * place * manner
datatype voice = Voiced | Voiceless
datatype place = Labial | Dental | Retroflex | Palatal | Velar | Glottal
datatype manner = Stop | Affricate | Fricative | Nasal | Lateral
type syllable = phoneme list

Does anyone have a particular way that they like to simulate this in Python?

A: 

You could create classes that contain the attributes you need.

class Phoneme:
    # ...

class Consonant(Phoneme):
    def __init__(self, voice, place, manner):
        self.voice = voice
        self.place = place
        self.manner = manner
    # ...

h = Consonant('Voiceless', 'Glottal', 'Fricative')
# ...
dan04
Note that it is best always to inherit `object` rather than nothing (`class Phoneme(object)`) so that you are using new-style classes.
Mike Graham
new-style classes are still not inherited by default?
dash-tom-bang
+1  A: 

For the simple enumerations like voice, place and manner you could use a class like this:

class Enum(object):
   def __init__(self, *values):
      self._values = set(values)
      for value in values:
         setattr(self, value, value)
   def __iter__(self):
      return iter(self._values)

place = Enum('Labial', 'Dental', 'Retroflex', 'Palatal', 'Velar', 'Glottal')

a = place.Retroflex    
if a == place.Labial:
   print "How did this happen?"

for p in place:
   print "possible value:", p
sth
It is not clear to me how this solution is worth while. Can you help me understand?
Mike Graham
+1  A: 

As sth indicated, your voice, place, and manner types are just enumerated types. There are a number of ways to implement those, such as

class voice(object):
  Voiced, Voiceless = range(2)

Then you can refer to voice.Voiced and voice.Voiceless, and so forth.

The problem is types like phoneme. In C the usual way to implement something like that would be to hold your nose and use a union. In something like python, you use polymorphism. First, figure out what operations you're going to perform on the phoneme type. Then, implement those operations as member functions of a Vowel class and a Consonant class. In C++ you'd make those member functions virtual and make an abstract base class for Vowel and Consonant; in python you can get away without doing that thanks to duck typing, although you might still find a base class to be useful.

So,

class Vowel(object):
  def SomeInitialMethod(self):
    # ...

class Consonant(object):
  def SomeInitialMethod(self):
    # ...

p.SomeInitialMethod() # p can be either vowel or consonant

def SomeLaterFunction(p)
  # p is assumed to be either a Vowel or a Consonant
  if isinstance(p, Vowel):
    # ...
  elif isinstance(p, Consonant):
    # ...
Peter Milley