3 votes

La fonction d'annotation avec filtre provoque une erreur trop générique

J'essaie de créer une fonction générique capable d'accepter un fichier Maybe List de tout enregistrement avec un id : Int comme champ, pour savoir si un id existe dans cette liste. Le retour peut être l'un des trois états suivants : le Found record , NotFound et un Loading message (pour les cas où la liste est Nothing ).

Les erreurs m'ont conduit à ce code jusqu'à présent, mais je suis maintenant bloqué et je ne comprends pas comment résoudre ce problème à partir de l'aide à l'erreur (y compris la lecture de le lien ). Comment faire pour que cela fonctionne, et pourquoi exactement cela ne fonctionne-t-il pas ?

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" ])

Editer

L'erreur :

-- 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>

Je comprends que le type d'enregistrement du filtre et de l'en-tête ne correspondra pas nécessairement. a mais ne sait pas comment résoudre le problème.

4voto

Chad Points 596

La compilation s'effectuera avec succès si vous redéfinissez Find a de manière plus générique :

type Find a
  = Found a
  | NotFound
  | Loading

Ou, si l'on conserve la définition de Find a telle que vous l'avez codée à l'origine, vous pourriez annoter votre fonction comme suit :

findById : Int -> Maybe (List (RecordWithID a)) -> Find a

Pourquoi cela fonctionne-t-il ainsi ? Je ne peux qu'émettre des hypothèses. Il n'en reste pas moins qu'il n'y a pas de problème. sent un peu comme une contrainte de classe de type en Haskell (par ex. findById :: Record a => Int -> Maybe (List a) -> Find a puisque a dans la version Elm ne peut être contraint qu'une seule fois dans l'annotation. Je ne sais pas si c'est vrai pour le compilateur, mais c'est ce que j'ai l'impression. Encore une fois, ce n'est que de la spéculation.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X