I am trying to create a generic function to be able to accept a Maybe List of any record with an id : Int as a field, to find if an id exists in that list. The return could be one of three states, the Found record, NotFound, and a Loading message (for when the list is Nothing).
The errors have led me to this code so far, but am now stuck and don't understand how to fix this from the the error help (including reading through the link). How can I get this to work, and why exactly does this not work?
import Html exposing (text)
type alias RecordWithID a =
{ a | id : Int }
type alias MyRecord =
{ id : Int
, name : String
}
type Find a
= Found (RecordWithID a)
| NotFound
| Loading
findById : Int -> Maybe (List (RecordWithID a)) -> Find (RecordWithID a)
findById id maybeItems =
case maybeItems of
Just items ->
let
head = List.head <| List.filter (\x -> x.id == id) items
in
case head of
Just item ->
Found item
Nothing ->
NotFound
Nothing ->
Loading
main = text <| toString <| findById 4 (Just [ MyRecord 4 "hi" ])
The error:
-- TYPE MISMATCH ---------------------------------------------------------------
The type annotation for `findById` does not match its definition.
17| findById : Int -> Maybe (List (RecordWithID a)) -> Find (RecordWithID a)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The type annotation is saying:
Int -> Maybe (List { b | id : Int }) -> Find { b | id : Int }
But I am inferring that the definition has this type:
Int -> Maybe (List { b | id : Int }) -> Find b
Hint: A type annotation is too generic. You can probably just switch to the type
I inferred. These issues can be subtle though, so read more about it.
<https://github.com/elm-lang/elm-compiler/blob/0.17.0/hints/type-annotations.md>
I understand that the type of the record from the filter and head won't necessarily match a, but unsure on how to resolve the problem.
This will compile successfully if you redefine Find a more generically:
type Find a
= Found a
| NotFound
| Loading
Or, if you kept the definition of Find a as you originally coded it, you could annotate your function like this:
findById : Int -> Maybe (List (RecordWithID a)) -> Find a
Why does it work this way? I can only speculate. It feels a little like a typeclass constraint in Haskell (e.g. findById :: Record a => Int -> Maybe (List a) -> Find a, since a in the Elm version is only allowed to be constrained in the annotation once. I don't know whether this is true when it comes to the compiler but that's what it feels like. Again, that's just speculation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With