Restrict records using Opaque Types
This topic has been covered by Elm Patterns​
If you're writing a package use a pipeline API instead.
Problem
Solution
Main.elm
type alias Movie =
{ title : String
, rating : Int
}
​
{-| adds a Rating to a Movie,
Only allows ratings between 1 and 5.
-}
addRating : Int -> Movie -> Movie
addRating rating movie =
{ movie | rating = rating}
Movie.elm
module Movie exposing (Movie,fromTitle,addRating)
​
type Movie =
Movie
{ title : String
, rating : Int
}
​
{-| adds a Rating to a Movie,
Only allows ratings between 1 and 5.
-}
addRating : Int -> Movie -> Maybe Movie
addRating rating (Movie movie) =
if 1 <= rating && rating <= 5 then
Just <| Movie { movie | rating = rating}
else
Nothing
​
{-| Constructs a Movie from a Title
-}
fromTitle : String -> Movie
fromTitle title =
Movie
{ title = title
, rating = 0
}
Main.elm
import Movie exposing (Movie)
​
newMovie : String -> Int -> Movie
newMovie title rating =
let
movie = Movie.fromTitle title
in
movie
|> Movie.addRating rating
|> Maybe.withDefault movie

Question

How can I only allow specific states for my type?

Answer

Place the type into a new File and don't expose the constructor: exposing (Movie) instead of exposing(Movie(..)). Then write your own constructors.
We can unwrap function parameters like this:
addRating rating (Movie movie) =
...

Further reading

Copy link
On this page
Question
Answer
Further reading