-
Notifications
You must be signed in to change notification settings - Fork 6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[RFC] Find best solution for dealing with (phantom) type variables #45
Comments
I would like to propose another solution. We can take advantage of extensible records to implement this. See example bellow: type Id a = Id String
type alias WithId r = { r | id : Id r }
type alias User = WithId
{ name : String
, age : Int
}
user : User
user =
{ id = Id "1"
, name = "Jane Doe"
, age = 54
} in repl:
How does it work?With usage of extensible record, we exclude the This illustrates what is going on (repl):
Drawback
|
I just come up with another trick using extensible records that might be even more useful: type Id a
= Id String
type OwnId
= OwnId String
type alias User =
{ id : OwnId
, name : String
, age : Int
}
getId : { a | id : OwnId } -> Id { a | id : OwnId }
getId rec =
case rec.id of
OwnId str ->
Id str
user : User
user =
{ id = OwnId "1"
, name = "Jane Doe"
, age = 54
}
userId : Id User
userId =
getId user loaded to repl:
All we need to do is to generate UpdateI also managed to break this: type Own a
= Own a
type Tag a t
= Tag a
type alias OwnId =
Own String
type alias Id t =
Tag String t
getOwn : (a -> Own b) -> a -> Tag b a
getOwn get val =
case get val of
Own a ->
Tag a
getId : { a | id : OwnId } -> Id { a | id : OwnId }
getId =
getOwn .id
type alias Post =
{ id : OwnId
, text : String
, userId : Id User
}
type alias User =
{ id : OwnId
, name : String
, age : Int
, posts : List (Id Post)
}
post : Post
post =
{ id = Own "1"
, text = "FooBar"
, userId = getId user
}
user : User
user =
{ id = Own "1"
, name = "Jane Doe"
, age = 54
, posts = [ getId post ]
} will again result in recursion:
|
Did anyone make any progress here? Especially in the simple case of a datatype like:
especially when I can, at compile-time, tell elm-street what concrete
? |
It's highly desired to have datatypes with phantom type variables. Like this one:
But there are problems with using such data types in Elm. For example, if we have the following Haskell data type:
then
elm-street
generates the following Elm definition:Unfortunately, this is invalid Elm (version 0.19) and produces the following error:
This is not restricted only to phantom type variables, we can't have type aliases that reference themselves. So we need to do better. I would like to discuss possible solutions to this problem and choose the most ergonomic one.
Solution 1: Drop phantom type variables on frontend and tell custom compiler error [current solution]
Instead of preserving phantom type variables on the frontend, we just drop them:
If you derive
Elm
typeclass for data types with type variables, the following compiler error is shown:Solution 2: Generate fake data type for using in phantom variables
Type aliases can refer to themselves. But they can refer to some other types.
Solution 3: Always create
type
instead oftype alias
Just don't generate type aliases at all. Always create
type
:This might be less convenient to use.
Solution 4: Generate
type
instead oftype alias
only when the type alias reference itselfThis is hard to implement, because we need to implement algorithms for finding cycles in data type definitions.
The text was updated successfully, but these errors were encountered: