Imagine you try to design "factories". You have factories that can build Diesel cars, and factories that can build any kind of car (Diesel and Gas, but other kinds of cars could exist). Let's say you want the user to be able to create their customized car factory, for which you provide an API, like
I have a module Factory which defines a Factory and a Car type, all opaque. I provide two functions createCarFactory
and createDieselCarFactory
, where the first one takes a use-provided function that can return a list of any cars (and they can be mixed), and the second one can only generate Diesel cars.
I want the garantee as the module author, that users won't be able to provide functions that create cars other than diesel cars in the createDieselCarFactory
, while still allowing to create any kind of car with the createCarFactory
function.
I want the type system to be the one to complain if these guarantees are not respected by the user.
For simplicity's sake, imagine that cars have no data.
The following is an example of the API could look like, but without the garantees I mentioned. You are allowed to tweak change it however you want.
module Factory exposing (Factory, createCarFactory, createDieselCarFactory, Car, gasCar, dieselCar)
type Car = DieselCar | GasCar
createDieselCarFactory : (data -> List Car) ->Factory
createCarFactory : (data -> List Car) -> Factory
gasCar = GasCar
dieselCar = DieselCar
This is how the API could be used:
import Factory
-- Ok. notice that there are different variants of the car in the resulting list
factory : Factory
factory =
Factory.createCarFactory (\_ -> [ Factory.dieselCar, Factory.gasCar ])
-- Also ok
factory : Factory
factory =
Factory.createDieselCarFactory (\_ -> [ Factory.dieselCar ])
-- NOT OK
factory : Factory
factory =
Factory.createDieselCarFactory (\_ -> [ Factory.dieselCar, Factory.gasCar ])
This is awesome. Thanks for sharing :)