Elm 中的类型不匹配

Type Mismatch in Elm

我刚刚开始学习 Elm,但我很难理解为什么在将自定义类型传递到期望的方法时会出现类型不匹配的问题……好吧,我称之为部分类型注释。

这是我使用的代码:

import Graphics.Element exposing (show)
import Debug

type User =
  User { username : String, followers : List User }

type Action = Follow

fromJust : Maybe a -> a
fromJust x = case x of
    Just y -> y
    Nothing -> Debug.crash "error: fromJust Nothing"

update : User 
  -> Action 
  -> { user | followers : List User } 
  -> { user | followers : List User }
update actor action user =
  case action of  
    Follow -> { user | followers = user.followers ++ [actor] }

getUsers : List User
getUsers =
  [
    User { username = "UserA", followers = [] },
    User { username = "UserB", followers = [] }
  ]

main =
  let 
    users = getUsers 
    first = fromJust (List.head users)
    last = fromJust (List.head (List.reverse users))
  in
  show (update first Follow last)

以及elm-lang.org/try的错误输出:

类型不匹配

函数 update 的第三个参数导致不匹配。

43| show(先更新,后更新) 函数 update 期望第三个参数为:

{ a | followers : List User }

但它是:

User

提示:我总是从左到右找出参数的类型。如果 当我检查它时参数是可以接受的,我假设它是 "correct" 随后 检查。所以问题实际上可能在于先前的论点如何与 第三个


如果我将 update 的类型注释改为 User,我会得到一个不同的类型不匹配,说我应该改回类型。 :困惑:

是因为递归类型。 Elm 似乎没有特别直观的(无论如何对 Haskeller 来说)处理这些,你必须在那里放一些明确的展开和包装才能使它全部工作。我假设编译器引导您定义了您拥有的 User 类型,就像我开始使用它时一样。

虽然这一切的结果是,您的示例中 User 类型的值不是记录,它们是将记录作为参数的数据构造函数。你必须对这些值进行模式匹配才能得到记录,并且记住在你 return 这样的值时包含构造函数。幸运的是 Elm 有很好的模式匹配支持,否则这将是可怕的。

因此,如果您将 update 函数更改为

update : User 
  -> Action 
  -> User
  -> User
update actor action (User user) =
  case action of  
    Follow -> User { user | followers = user.followers ++ [actor] }

一切正常。注意现在参数都是User类型,user参数正在解构,所以我们可以拿到里面的记录。最后,使用 User 数据构造函数重建结果。