In Haskell, I have a module with a partial order type:
data PartialOrder a = PartialOrder [a] [(a, a)]
I don't export the value constructor because that's not how I want the type to be used, but I still want to be able to pattern match the PartialOrder type outside the module; is this possible? In particular, I want to be able to pattern match something that is not the type constructor, but instead, to pattern match something like the following:
f (PartialOrder xs le) = ...
Where le
is a function implicitly defining the explicit ordering defined in the value constructor. I know such a facility is available in Scala, is there a way to do the same in Haskell?
Thanks in advance.
It sounds like a use case for ViewPatterns
. You could write a type like:
data ViewPartialOrder a = ViewPartialOrder a (a -> a -> Ordering)
Write a function like:
viewOrder :: PartialOrder -> ViewPartialOrder
viewOrder (PartialOrder xs relation) = ...
then use the ViewPatterns
extension to write code like this:
f (viewOrder -> ViewPartialOrder xs le) = ...
Of course, you should come up with better names for these things :P!
There's no way to have the same effect implicitly (ie without the viewOrder
function), for better or worse. I think it's usually a good thing, making it clear that you're not matching the actual implementation of the type.
The suggestion to use a view pattern is a fine one, but you can get much the same effect without a view pattern by precomposing with the "view" which is, after all, just a function.
So given
viewOfPartialOrder :: PartialOrder -> ViewPartialOrder
viewOfPartialOrder (PartialOrder xs relation) = ...
as suggested by Tikhon Jelvis (under a slightly different name), instead of
doSomethingWithAPartialOrder :: PartialOrder a -> Whatever
doSomethingWithAPartialOrder (viewOfPartialOrder -> ViewPartialOrder xs le) = ...
You can define
doSomethingWithAView :: ViewPartialOrder a -> Whatever
doSomethingWithAView (ViewPartialOrder xs le) = ...
doSomethingWithAPartialOrder :: PartialOrder a -> Whatever
doSomethingWithAPartialOrder = doSomethingWithAView . viewOfPartialOrder
Personally I find it easier to edit code presented in the latter way, but you should choose whatever you personally prefer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With