I would like to write a function that encodes a custom type Decision a
into JSON. The a
tag could be e.g. Accept
or Reject
, and I would like my function to call other functions depending on the type of the tag.
I have tried writing the case ... of
statement both in terms of the Decision
type as well as the tag, but have not been able to get either approach to work.
Here are my types:
type Decision a
= Decision Metadata a
type Accepted
= Accepted AcceptDetails
type Rejected
= Rejected RejectDetails
type alias Metadata =
{ time : Time.Posix }
type alias AcceptDetails =
{ comment : String }
type alias RejectDetails =
{ reasonCode : Int }
Now I would like to write an encoder that can take either type of decision. Something along the lines of:
encoder : Decision a -> Json.Encode.Value
encoder decision =
case decision of
Decision _ (Accepted _) ->
acceptedEncoder decision
Decision _ (Rejected _) ->
rejectedEncoder decision
This does not work but hopefully it conveys what I want - to route the encoding task to the appropriate function.
Is this possible? Or do I have to solve it another way, e.g. by directly calling the right encoder depending on the kind of decision?
I suppose there is a catch in the fact that a
could be anything, but, perhaps naively, that could be handled by adding a _
case as well.
The compiler gives the error message:
The first pattern is trying to match `Decision` values of type:
Decision Accepted
But the expression between `case` and `of` is:
Decision a
If the a
in Decision a
is only ever going to be either an Approved
or Rejected
type, it seems that merging the two constructors into a single type would be appropriate.
type DecisionResult
= Accepted AcceptDetails
| Rejected RejectDetails
This would remove the need for the type parameter on Decision
:
type Decision
= Decision Metadata DecisionResult
Your encoder
function could then route the decision metadata and approved/rejected details to the more specific encoders:
encoder : Decision -> Json.Encode.Value
encoder (Decision meta result) =
case result of
Accepted details ->
acceptedEncoder meta details
Rejected details ->
rejectedEncoder meta details
acceptedEncoder : Metadata -> AcceptDetails -> Json.Encode.Value
acceptedEncoder meta details =
...
rejectedEncoder : Metadata -> RejectDetails -> Json.Encode.Value
rejectedEncoder meta details =
...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With