Elm中的类型失配

Elm中的类型失配,elm,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

我刚刚开始学习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)
以及以下各项的错误输出:

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

43 |显示(先更新后更新) 函数
update
希望第三个参数为:

{ a | followers : List User }
但事实是:

User
提示:我总是从左到右找出参数的类型。如果 参数是可以接受的,当我检查它时,我假设它在后续的测试中是“正确的” 检查。所以问题可能在于之前的论点是如何与 三号



如果我更改了
update
的类型注释,以期望得到一个
用户
,我会得到一个不同的类型不匹配,说我应该将类型更改回去:困惑:

这是因为递归类型。Elm似乎没有特别直观的(无论如何对Haskeller来说)处理这些,您必须在其中放入一些明确的展开和包装,以使所有工作正常。我假设编译器引导您找到您拥有的
用户
类型的定义,就像我开始使用它时一样

但结果是,在您的示例中,
User
类型的值不是记录,而是将记录作为参数的数据构造函数。为了获得记录,必须对这些值进行模式匹配,并记住在返回此类值时包含构造函数。幸运的是,Elm有很好的模式匹配支持,否则这将是可怕的

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

update : User 
  -> Action 
  -> User
  -> User
update actor action (User user) =
  case action of  
    Follow -> User { user | followers = user.followers ++ [actor] }
一切正常。请注意,参数现在都是
User
类型,并且
User
参数正在解构,以便我们可以查看内部记录。最后,使用
用户
数据构造函数重构结果