types和types别名之间的差异?
在榆树,我不明白何时type
是适当的关键字与type alias
。 文档似乎没有对此的解释,也不能在发行说明中find。 这是logging在某处吗?
我如何看待它:
type
用于定义新的联合types:
type Thing = Something | SomethingElse
在这个定义之前, Something
和SomethingElse
没有任何意义。 现在他们都是我们刚刚定义的那种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
是一个String
和aliasedStringIdentity
需要一个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