I want to create a map at compile time that maps compile time keys to run time values. Functions should be able to check for those keys and throw a compiler error if all not all of the required keys are present.
This is roughly what I’d like to achieve:
class HasFirst a
first :: String
class HasMiddle a
middle :: String
class HasLast a
last :: String
print_full_name :: (HasFirst a, HasLast a) => a -> String
addFirst :: String -> a -> b
addFirst s x = -- ( Add a first name to x )
emptyName :: -- some empty name
x1 = addFirst "John" $ addLast "Smith" $ emptyName
x2 = addMiddle "Bob" $ addLast "Smith" $ emptyName
main = putStr $ print_full_name x1 -- Compiles
main = putStr $ print_full_name x2 -- No first name so compile error
For those with C++ knowledge, I want roughly what boost::fusion::map does.
I don’t need exactly the code above, what is important that I can check parameters at compile time. Whether the mechanism is classes or something else I don’t mind.
Is there a package that does this or is it easy to develop this?
Let me tell you how you can get your example to work using a functional design technique called phantom types:
We use the three type parameters of
Nameto track which names have been set.printFullNameonly accepts names with first and last names. We get a type error when trying to print underdefined names:Note that this is a very crude encoding, but hopefully it demonstrates the power of phantom types.