On Friday, February 10, 2017 at 3:26:38 PM UTC, Joey Eremondi wrote:
>
> So, Elm lets you do a forall over the rest of a record.
>
> {a | x : Int} -> Int says this function accepts any record that has an x
> Int field.
>
I am trying to build a model with states, such that fields are only
available that are actually needed in the relevant state. The model is like
this:
type alias WithPosition a =
{ a | rect : Rectangle }
type alias WithValue a =
{ a | value : String }
type State
= Hidden
| Aware (WithPosition {})
| Active (WithPosition (WithValue {}))
| Inactive (WithPosition (WithValue {}))
It can be convenient to have functions to work on fields in the model, only
when the state is such that those fields are available. Here is one such
function:
mapWhenWithPosition : (WithPosition {} -> a) -> State -> Maybe a
mapWhenWithPosition func state =
case state of
Aware { rect } ->
Just <| func { rect = rect }
Active { rect } ->
Just <| func { rect = rect }
Inactive { rect } ->
Just <| func { rect = rect }
_ ->
Nothing
So when in a state that is 'positioned' this function lets me apply a
function to the position and return the result in a Just, otherwise
Nothing. Makes it easy to have a UI component that will only appear in
certain states, for example.
What I don't understand is why this fails to type check:
mapWhenWithPosition : (WithPosition b -> a) -> State -> Maybe a
mapWhenWithPosition func state =
case state of
Aware rect ->
105: Just <| func rect
Active rect ->
Just <| func rect
Inactive rect ->
Just <| func rect
_ ->
Nothing
Complains that:
The argument to function `func` is causing a mismatch.
105| func rect
^^^^
Function `func` is expecting the argument to be:
WithPosition b
But it is:
WithPosition {}
I marked in which line is 105 above. The function WithPosition b -> a is
general enough to handle a WithPosition {}, but I seem to be only able to
use it where it fully matches.
This would seem to make extensible records a lot less useful than they
could be. Is this one of those cases where an existential qualifier would
be needed to specify the type of the function? Or is this in fact a case
that could be typed in Elm without problem and that the type checker should
accept?
Or perhaps there is some other way of writing what I want?
Inactive { rect } ->
Just <| func { rect = rect }
Isn't too bad, but it gets a lot worse when there are lots more fields and
you are having to deconstruct then reconstruct the same record:
SomeStatate { field1, field2, ..., fieldn } ->
Just <| func { field1 = field1, field2 = field2, ..., fieldn =
fieldn }
--
You received this message because you are subscribed to the Google Groups "Elm
Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.