Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to constraint input type and output type to be the same?

I am going through Type driven development with Idris from Manning. An example is given that teaches how to restrict a function to a given type in a family of types. We have Vehicle type that uses PowerSource that is either Pedal or Petrol and we need to write a function refill that typechecks only for vehicles that use petrol as their powersource.

The below code works, but does not guarantee that refilling a Car will produce a Car and not a Bus. How do I need to change the signature of the refill function to only allow producing Car when given a Car and producing Bus when given Bus?

data PowerSource
  = Pedal
  | Petrol

data Vehicle : PowerSource -> Type 
  where
    Bicycle : Vehicle Pedal
    Car : (fuel : Nat) -> Vehicle Petrol
    Bus : (fuel : Nat) -> Vehicle Petrol

refuel : Vehicle Petrol -> Nat -> Vehicle Petrol
refuel (Car fuel) x        = Car (fuel + x)
refuel (Bus fuel) x        = Bus (fuel + x)
like image 930
nohwnd Avatar asked Aug 13 '17 10:08

nohwnd


1 Answers

This can be achieved by introducing new VehicleType data type and by adding one more parameter to Vehicle like this:

data VehicleType = BicycleT | CarT | BusT

data Vehicle : PowerSource -> VehicleType -> Type 
  where
    Bicycle :                 Vehicle Pedal  BicycleT
    Car     : (fuel : Nat) -> Vehicle Petrol CarT
    Bus     : (fuel : Nat) -> Vehicle Petrol BusT

You should somehow encode in type difference between constructors. If you want more type safety you need to add more information to types. Then you can use it to implement refuel function:

refuel : Vehicle Petrol t -> Nat -> Vehicle Petrol t
refuel (Car fuel) x        = Car (fuel + x)
refuel (Bus fuel) x        = Bus (fuel + x)

Replacing

refuel (Car fuel) x        = Car (fuel + x)

with

refuel (Car fuel) x        = Bus (fuel + x)

leads to next type error:

Type checking ./Fuel.idr
Fuel.idr:14:8:When checking right hand side of refuel with expected type
        Vehicle Petrol CarT

Type mismatch between
        Vehicle Petrol BusT (Type of Bus fuel)
and
        Vehicle Petrol CarT (Expected type)

Specifically:
        Type mismatch between
                BusT
        and
                CarT
like image 172
Shersh Avatar answered Sep 21 '22 17:09

Shersh