Write safer functions using Phantom Types
Problem
Solution
1
type alias LoginForm =
2
{ username : String
3
, password : String
4
, isValid : Bool
5
}
6
​
7
{-| Creates a User
8
​
9
Only use this function if the LoginForm was validated.
10
-}
11
createUser : LoginForm -> User
12
createUser loginForm =
13
if loginForm.isValid then
14
User.create loginForm.username
15
else
16
Debug.todo "This should not happen."
Copied!
1
type LoginForm valid =
2
LoginForm
3
{ username : String
4
, password : String
5
}
6
​
7
type Valid = Valid
8
​
9
{-| Creates a User
10
-}
11
createUser : LoginForm Valid -> User
12
createUser (LoginForm loginForm) =
13
User.create loginForm.username
14
15
validate : LoginForm () -> LoginForm Valid
16
validate =
17
...
Copied!

Question

How can I ensure that a user can only be created with a valid login form?

Answer

Use a so called Phantom Type:
1
type LoginForm valid = --valid is not used in the definition
2
LoginForm
3
{ username : String
4
, password : String
5
}
6
7
type Valid = Valid
Copied!
Use LoginForm () for unvalidated forms and LoginForm Valid for validated ones.

Further reading