2012-07-02 3 views
3

Я есть типдизайн программы, касающиеся ADTS

data Phase = PhaseOne 
      | PhaseTwo 
      | PhaseThree deriving Enum 

и пять операций, чтобы сделать на каждом этапе

  • read
  • write
  • validate
  • evalStatus
  • update

Я начал пытаться создать класс типа. Проблема в том, что они все одинаковы. Я хотел бы быть в состоянии сделать что-то вроде

instance MyClass PhaseThree where 
    read a = ... 

Кроме того, мне нужно перегрузить тип возвращаемого значения.

Я знаю, что классы классов не то, что я хочу. Но я не уверен, как делать то, что я хочу. Я думал, что GADT, но это не совсем правильно, поскольку мне нужно иметь каждый экземпляр в отдельном файле.

Я хотел бы получить совет относительно того, какие механизмы мне нужно исследовать? Я дал достаточно информации?

+1

Если вы определяете отдельные функции для 'readPhaseOne',' readPhaseTwo', 'writePhaseOne',' writePhaseTwo' и т. Д., Какими будут их типы? – Heatsink

+1

это поможет, если у вас будет немного больше информации. Что именно вы пытаетесь достичь? Почему не работает обычное сопоставление шаблонов? Почему Фаза должна быть одним типом вместо трех? –

+0

Phillip: То, что я пытаюсь сделать, это сделать eDSL на основе вышеупомянутых операций. Обычное совпадение шаблонов не будет работать, потому что я пытаюсь перегрузить возвращаемый тип. Фаза должна быть перечислимым типом (нужен метод succ), поэтому может быть только один тип вместо трех (AFAIK). –

ответ

3

Я рекомендую немного изменить ситуацию.

data Phase = Phase { 
    read :: String -> Foo, 
    write :: Foo -> IO(), 
    validate :: Foo -> Bool, 
    evalStatus :: IO(), 
    update :: Foo -> Foo 
} 

phaseOne, phaseTwo, phaseThree :: Phase 

(или некоторые аналогичные переопределения классов в явные записи).

2

Разработав свой комментарий выше, если вы хотите использовать три разных типа с классом, поддерживающим ваши операции, вы можете сортировать сборку с помощью функции класса Enum с помощью метода класса succ.

Вы также должны обеспечить Done тип как заполнитель для succ PhaseThree

{-# LANGUAGE MultiParamTypeClasses , FunctionalDependencies #-} 
data PhaseOne = PhaseOne 
data PhaseTwo = PhaseTwo 
data PhaseThree = PhaseThree 

data Done = Done 

class YourClass p0 p1 | p0 -> p1 where 
    succ :: p0 -> p1 
    -- read :: ... 
    -- write :: ...etc 

instance YourClass PhaseOne PhaseTwo where 
    succ PhaseOne = PhaseTwo 
    -- read = ... 

instance YourClass PhaseTwo PhaseThree where 
    succ PhaseTwo = PhaseThree 

instance YourClass PhaseThree Done where 
    succ PhaseThree = Done 

Вы можете отделить Succ функциональности от ваших read, write и т.д. методов и создать два класса, а также. Возвращаемые значения могут быть полиморфными.

succ на вашей оригинальной опубликованной формулировке ужасно, так как succ PhaseThree просто выдает сообщение об ошибке. Если вы можете получить систему типов, работающих для вашего приложения, это идеальный вариант.

+0

Спасибо! Я собираюсь работать с этим. Я думаю, что это именно то, что мне нужно. –

+0

Отлично! обновляйте данные, если вы нажмете какие-либо помехи – jberryman

Смежные вопросы