gak
gak

Reputation: 32763

Function argument with a record destruct which is a single value union type, and alias

I'm using a union type with a single value for my ID to be type safe:

type PositionIdType = PositionId Int

Let's say I have a record:

type alias Position =
    { id : PositionIdType
    , x : Float
    , y : Float
    }

I understand I can do a record destruct:

function : Position -> a
function { id } =
    -- id is a PositionIdType

and similarly via assignment:

{ id } = Position (PositionId 99) 10 5

If I need to access the record too:

function : Position -> a
function ({ id } as position) =
    -- id is a PositionIdType
    -- position is a Position

And also destructing a single type:

function : PositionIdType -> a
function (PositionId id) =
    -- id is an Int

Also via assignment:

(PositionId id) = (Position (PositionId 99) 10 5).id

Is it possible to join these two together? I have tried a few different ways without success, e.g.:

getIdInt ((PositionId { id }) as position) = id
getIdInt ({(PositionId id)} as position) = id
getIdInt (({PositionId id}) as position) = id

My current solution is to do it in a let/in block, which works just fine, but would be very nice to skip the let block if possible:

processPosition : Position -> a
processPosition ({id} as position) =
    let
        (PositionId id_) =
            id
    in
        Http.post ("/position/" ++ id_) (positionEncoder position)

Upvotes: 1

Views: 756

Answers (1)

halfzebra
halfzebra

Reputation: 6797

As of today (0.18.0), destruncturing of nested Union Type value inside of the Record is impossible.

There's no info if this feature will ever land.

Here is a reference of record destructuring.

Tuple is the only Elm type, which allows nested destructuring.

nested ( x, ( y ) ) =  
  x + y

> nested ( 1, (1))
2 : number  

Destructuring of Union Type is only possible with if..else expression, case expression or when it is passed directly as an argument to the function.

Here's what I would have done, if I were to write getIdInt:

getIdInt : Position -> Int
getIdInt { id } =
  case id of
    PositionId val ->
      val

main =
  Position (PositionId 99) 10 5
    |> getIdInt
    |> toString
    |> text -- 99

Upvotes: 1

Related Questions