我正在尝试创建一个通用函数,以便能够接受Maybe List
作为字段id : Int
的任何记录,以查找该列表中是否存在id
。返回可以是三种状态之一:Found record
,NotFound
和Loading
消息(对于列表为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
匹配,但不确定如何解决问题。
答案 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
只允许在注释中约束一次。我不知道知道在编译器中这是否属实,但这就是它的感觉。再次,这只是推测。