2016-11-24 53 views

回答

13

讓我們首先看類型別名回答這個問題:

類型別名是完全透明的。這意味着任何其他導入它的模塊都可以完全訪問其內部工作。比方說,我們已經有了一個User模塊露出User類型:

module User exposing User 

type alias User = 
    { userName : String 
    , age : Int 
    } 

任何人進口User可以操縱數據,例如newUser = { oldUser | age = 25 }。或者做someUser = User "Bill" 27。當您控制它們存在的上下文時,這些操作很好。

但是,如果User是庫的一部分,那麼對User類型的每次更改都會對使用該庫的人造成重大改變。例如,如果在User中添加了email字段,則構造函數示例(someUser = User "Bill" 27)會給出編譯器錯誤。

即使在項目代碼庫的內部,類型別名也可以向其他模塊提供太多信息,從而導致難以維護和發展的代碼。在某些時候,User可能會發生急劇變化,並具有一組全新的屬性。無論代碼如何處理User s,都需要進行更改。

不透明類型是有價值的,因爲它們可以避免這些問題。下面是User不透明版本:

module User exposing User 

type User = 
    User 
     { userName : String 
     , age : Int 
     } 

在這個版本中,其他模塊不能直接訪問或操縱數據。通常情況下,這意味着你將和揭露一些getter和功能:

initUser : String -> Int -> User 
userName : User -> String 
age : User -> String 
setAge : Int -> User -> User 

這是更多的工作,但它的優點:

  • 其它模塊只關心User功能,不需要知道的是在類型
  • 類型可以不破壞模塊包含

之外的代碼更新哪些數據210

這在很大程度上解釋來自@wintveltelmlang.slack.com

+0

下面是庫的作者和包約值一些更多的討論:http://package.elm-lang.org/help/design-guidelines#keep-tags -and-record-constructors-secret – Nathan

+0

感謝分享這個解釋。因爲它的大約一半是我早些時候在Slack([這裏](https://elmlang.slack.com/archives/design-patterns/p1480011953000265))上發佈的答案的確切副本,所以提及或鏈接應該是不錯。 – wintvelt

+1

嘿@wintvelt:對不起!我認爲這是一個非常好的答案,有助於生活在更加持久的地方。我爲您的SO帳戶添加了一個參考。也許一個SO MOD可以將你添加爲作者? – Nathan