What is an opaque type in Elm and why is it valuable?

后端 未结 1 1559
夕颜
夕颜 2021-02-05 12:40

I\'ve used types before but don\'t know what an opaque type is. I\'ve seen it mentioned as well. Is it better to expose an opaque type than a type alias?

相关标签:
1条回答
  • 2021-02-05 12:56

    Let’s answer this question by first looking at type aliases:

    A type alias is fully transparent. This means that any other module importing it will have full access to its inner workings. Let’s say we’ve got a User module exposing a User type:

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

    Anyone importing User can manipulate the data, e.g. newUser = { oldUser | age = 25 }. Or do someUser = User "Bill" 27. These manipulations are fine when you have control over the context that they exist in.

    However, if User is part of a library then every change to the User type is a breaking change to people that use the library. For example, if an email field is added to User, then the constructor example (someUser = User "Bill" 27) will give a compiler error.

    Even inside of a project codebase, a type alias can provide too much information to other modules which leads to code that is difficult to maintain and evolve. Perhaps a User changes drastically at some point and has a completely new set of properties. This would require changes wherever the code manipulates Users.

    Opaque types are valuable because they avoid these issues. Here’s an opaque version of User:

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

    With this version, other modules cannot access or manipulate the data directly. Often, this means you will make and expose some getter and functions:

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

    This is more work, but it has advantages:

    • Other modules only care about the User functions and don’t need to know what data is in the type
    • The type can be updated without breaking code outside the containing module

    Much of this explanation comes from @wintvelt: elmlang.slack.com

    0 讨论(0)
提交回复
热议问题