我刚刚开始学习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
提示:我总是从左到右弄清楚参数的类型。如果 当我检查它时,参数是可以接受的,我认为它在随后是“正确的” 检查。所以问题可能实际上在于先前的参数如何与之相互作用 第3次。
如果我将update
的类型注释更改为期望User
,我会得到一个不同的类型不匹配,说我应该更改类型。 :困惑:
答案 0 :(得分:2)
这是因为递归类型。榆树似乎没有特别直观(对于Haskeller来说)处理这些,你必须在那里做一些明确的展开和包装以使它全部工作。我假设编译器引导您进入User
类型的定义,就像我开始玩它时一样。
尽管如此,示例中类型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
参数正在被解构,因此我们可以获取内部记录。最后,使用User
数据构造函数重建结果。