types和types别名之间的差异?

在榆树,我不明白何时type是适当的关键字与type alias 。 文档似乎没有对此的解释,也不能在发行说明中find。 这是logging在某处吗?

    我如何看待它:

    type用于定义新的联合types:

     type Thing = Something | SomethingElse 

    在这个定义之前, SomethingSomethingElse没有任何意义。 现在他们都是我们刚刚定义的那种types的Thing

    type alias用于给一个已经存在的其他types的名称:

     type alias Location = { lat:Int, long:Int } 

    { lat = 5, long = 10 }types为{ lat:Int, long:Int } ,这已经是一个有效的types。 但是现在我们也可以说它具有types的Location因为这是同一types的别名。

    值得注意的是,下面的内容会编译得很好,并显示"thing" 。 即使我们指定的thing是一个StringaliasedStringIdentity需要一个AliasedString ,我们不会得到一个错误,有一个types不匹配之间的String / AliasedString

     import Graphics.Element exposing (show) type alias AliasedString = String aliasedStringIdentity: AliasedString -> AliasedString aliasedStringIdentity s = s thing : String thing = "thing" main = show <| aliasedStringIdentity thing 

    关键是alias 。 在编程的过程中,当你想把属于一起的东西分组时,你把它放在一个logging中,就像一个点

     { x = 5, y = 4 } 

    或学生logging。

     { name = "Billy Bob", grade = 10, classof = 1998 } 

    现在,如果您需要传递这些logging,则必须将整个types拼写出来,例如:

     add : { x:Int, y:Int } -> { x:Int, y:Int } -> { x:Int, y:Int } add ab = { ax + bx, ay + by } 

    如果你可以别名,那么签名会容易得多!

     type alias Point = { x:Int, y:Int } add : Point -> Point -> Point add ab = { ax + bx, ay + by } 

    所以一个别名是其他东西的简写。 在这里,这是一个loggingtypes的简写。 你可以把它想象成一个你经常使用的loggingtypes的名字。 这就是为什么它被称为别名 – 它是由{ x:Int, y:Int }表示的裸体loggingtypes的另一个名称

    type解决了另一个问题。 如果你是从OOP来的,那么你就是通过inheritance,运算符重载等解决的问题 – 有时候,你想把数据视为一个通用的东西,有时你想把它当作一个特定的东西来对待。

    发生这种情况的普遍现象是传递邮件时 – 比如邮政系统。 当你发信时,你希望邮政系统把所有邮件视为同一件事,所以你只需要devise邮政系统一次。 此外,路由消息的工作应该独立于其中包含的消息。 只有当信件到达目的地时,你才会关心信息是什么。

    以同样的方式,我们可以将一个type定义为所有可能发生的不同types的消息的联合。 假设我们正在实施大学生与父母之间的信息系统。 所以大学生只能传送两条消息:“我需要啤酒钱”和“我需要内裤”。

     type MessageHome = NeedBeerMoney | NeedUnderpants 

    所以现在,当我们devise路由系统的时候,我们的函数的types可以通过MessageHome传递,而不用担心所有不同types的消息。 路由系统不关心。 它只需要知道它是一个MessageHome 。 只有当消息到达目的地时,父母的家,你需要弄清楚它是什么。

     case message of NeedBeerMoney -> sayNo() NeedUnderpants -> sendUnderpants(3) 

    如果您知道Elm体系结构,则更新函数是一个巨大的case语句,因为这是消息路由的目的地,因此被处理。 而且我们使用uniontypes在传递消息的时候有一个单独的types来处理,但是可以使用case语句去清楚它到底是什么消息,所以我们可以处理它。

    正如我所看到的,主要区别在于,如果使用“synomical”types,types检查器是否会对你大喊大叫。

    创build下面的文件,放到某个地方并运行elm-reactor ,然后转到http://localhost:8000来查看区别:

     -- Boilerplate code module Main exposing (main) import Html exposing (..) main = Html.beginnerProgram { model = identity, view = view, update = identity } -- Our type system type alias IntRecordAlias = {x : Int} type IntRecordType = IntRecordType {x : Int} inc : {x : Int} -> {x : Int} inc r = {r | x = .xr + 1} view model = let -- 1. This will work r : IntRecordAlias r = {x = 1} -- 2. However, this won't work -- r : IntRecordType -- r = IntRecordType {x = 1} in Html.text <| toString <| inc r 

    如果您取消注释2.并注释1.您将看到:

     The argument to function `inc` is causing a mismatch. 34| inc r ^ Function `inc` is expecting the argument to be: { x : Int } But it is: IntRecordType