带过滤器的注释函数导致过于一般的错误

时间:2016-07-06 08:08:03

标签: generics elm

我正在尝试创建一个通用函数,以便能够接受Maybe List作为字段id : Int的任何记录,以查找该列表中是否存在id。返回可以是三种状态之一:Found recordNotFoundLoading消息(对于列表为Nothing时)。

错误导致我到目前为止这个代码,但我现在卡住了,并且不理解如何从错误帮助中解决这个问题(包括阅读the link)。我怎样才能使这个工作,以及为什么这不起作用?

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

修改

错误:

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

我理解过滤器和头部的记录类型不一定与a匹配,但不确定如何解决问题。

1 个答案:

答案 0 :(得分:4)

如果您更通用地重新定义Find a,这将成功编译:

type Find a
  = Found a
  | NotFound
  | Loading

或者,如果您保留Find a的定义,就像您最初编码它一样,您可以像这样注释您的函数:

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

为什么这样工作?我只能推测。它感觉有点像Haskell中的类型类约束(例如findById :: Record a => Int -> Maybe (List a) -> Find a,因为Elm版本中的a只允许在注释中约束一次。我不知道知道在编译器中这是否属实,但这就是它的感觉。再次,这只是推测。