2013-12-21 2 views
5

В Haskell, у меня есть модуль с типом частичного порядка:Можно ли создать произвольное разложение шаблонов в Haskell?

data PartialOrder a = PartialOrder [a] [(a, a)] 

Я не экспортировать конструктор значение, потому что это не так, как я хочу, чтобы типа, которые будут использоваться, но я все равно хочу, чтобы иметь возможность шаблон соответствует типу PartialOrder вне модуля; Это возможно? В частности, я хочу, чтобы иметь возможность сопоставления с образцом чего-то, что не является конструктором типа, но вместо того, чтобы матч шаблон что-то вроде следующего:

f (PartialOrder xs le) = ... 

Где le является функция неявно определяющая явный порядок, определенный в конструктор значений. Я знаю, что такое средство доступно в Scala, есть ли способ сделать то же самое в Haskell?

Заранее спасибо.

ответ

12

Это звучит как прецедент для ViewPatterns. Вы можете написать типа, как:

data ViewPartialOrder a = ViewPartialOrder a (a -> a -> Ordering) 

Написать функцию, как:

viewOrder :: PartialOrder -> ViewPartialOrder 
viewOrder (PartialOrder xs relation) = ... 

затем использовать расширение ViewPatterns писать код, как это:

f (viewOrder -> ViewPartialOrder xs le) = ... 

Конечно, вы должны прийти с лучшими именами для этих вещей: P!

Невозможно иметь такой же эффект неявно (т.е. без функции viewOrder), к лучшему или к худшему. Я думаю, что это, как правило, хорошая вещь, давая понять, что вы не соответствуете фактической реализации типа.

+0

Ударьте меня секундами! –

+0

@ChrisTaylor: Хорошее старомодное «самое быстрое оружие в западной проблеме»: P. –

+1

Новое расширение PatternSynonyms предоставит вам то, что вы хотите, но пока не совсем доступно. – augustss

3

Предложение использовать шаблон представления является прекрасным, но вы можете получить такой же эффект без шаблона представления, предварительно создавая «вид», который, в конце концов, является просто функцией.

Так дали

viewOfPartialOrder :: PartialOrder -> ViewPartialOrder 
viewOfPartialOrder (PartialOrder xs relation) = ... 

как предложено Тихона Jelvis (под несколько иным названием), вместо

doSomethingWithAPartialOrder :: PartialOrder a -> Whatever 
doSomethingWithAPartialOrder (viewOfPartialOrder -> ViewPartialOrder xs le) = ... 

Вы можете определить

doSomethingWithAView :: ViewPartialOrder a -> Whatever 
doSomethingWithAView (ViewPartialOrder xs le) = ... 

doSomethingWithAPartialOrder :: PartialOrder a -> Whatever 
doSomethingWithAPartialOrder = doSomethingWithAView . viewOfPartialOrder 

Лично я считаю, что проще для редактирования кода, представленного последним способом, но вы должны выбрать то, что вы лично предпочитаете.

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