haskelltypestype-systemsrefinement-typeliquid-haskell

Can I define parametric data type where parameters are not equals between in Haskell?


Problem:

Let's imagine we have a Passenger with start and end points represented by:

data Passenger a = Passenger { start :: a
                               , end :: a
                             }

Question:

How can I apply a class constraints to Passenger, where the start point shouldn't be equal to the end point?

P.S.: I have asked a similar question in the Scala community, but I didn't receive any answer. Considering that refined library for scala is inspired by refined for Haskell, also hearing about liquid-Haskell, I wonder how can resolve it using Haskell?


Solution

  • I just saw this. You can do so by specifying a refinement on the end field, e.g.:

    {-@ data Passenger a = Passenger 
          { start :: a
          , end   :: {v:a | v /= start} 
          } 
      @-}
    
    data Passenger a = Passenger 
      { start :: a
      , end   :: a
      }                        
    
    ok :: Passenger String 
    ok = Passenger "Alice" "Jones"
    
    bad :: Passenger String
    bad = Passenger "Bora" "Bora"
    

    You can play with this online here:

    http://goto.ucsd.edu:8090/index.html#?demo=permalink%2F1551137259_16583.hs