Created
November 25, 2020 14:42
-
-
Save Savelenko/dd50e27688672371d1f8eaf35c4adc54 to your computer and use it in GitHub Desktop.
What if F# had type families
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(* What if F# had type families? *) | |
// We are a message processing system. There are regular and confidential messages to be delivered. Several delivery | |
// methods are supported. The main "business rule" is that regular messages must be sent by e-mail and confidential | |
// messages by post. | |
// Delivery methods. | |
type EMail = DeliveryMethodEmail of string | |
type Post = DeliveryMethodPost of {| RecipientName : string; Address : string |} | |
// Regular and confidential messages. | |
type Message = Message of string | |
type ConfidentialMessage = { | |
Contents : string | |
Signature : int | |
} | |
// A type family is like a function, only not accepting and returning values, but types. | |
type family DeliveryMethod<'m> where | |
DeliveryMethod<Message> = Email | |
DeliveryMethod<ConfidentialMessage> = Post | |
// Remember we are a message processing system, so there is a message queue somewhere. Now we can statically ("in the | |
// type system") enforce that messages are sent only using the required delivery method. It is not possible to add a | |
// message to the send queue with a wrong delivery method. | |
type DeliveryQueueItem<'m> = { | |
Message : 'm | |
Method : DeliveryMethod<'m> | |
} | |
// The following is OK. | |
let regularQueue = [ | |
{ Message = Message "You sleepy?"; Method = EMail "totoro@bigtree.net"} | |
// Other regular messages here... | |
] | |
// This would not compile because (EMail ...) is not a value of type DeliveryMethod<ConfidentialMessage>. | |
let confidentialQueue = [ | |
{ Message = ConfidentialMessage { Contents = "A secret"; Signature = 666 }; Method = EMail "me@home.com" } | |
] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment