agrafix / elm-bridge

Haskell: Derive Elm types from Haskell types
BSD 3-Clause "New" or "Revised" License
100 stars 27 forks source link

Consider adding Tagged instance #29

Closed paparga closed 6 years ago

paparga commented 6 years ago

Hi!, we use a lot phantom types with Tagged, currently are derived like this:

data EmailT
type Email = Tagged EmailT Text
type alias User  =
   { name: String
   , email: Email
   }

jsonDecUser : Json.Decode.Decoder ( User )
jsonDecUser =
   ("name" := Json.Decode.string) >>= \pname ->
   ("email" := jsonDecEmail) >>= \pemail ->
   Json.Decode.succeed {name = pname, email = pemail}
bartavelle commented 6 years ago

What would be the proper Elm code?

type alias Email = String
type alias User  =
   { name: String
   , email: Email
   }

?

paparga commented 6 years ago

Sorry for not being clear, the problem is that jsonDecEmail it's not defined. some alternatives:

1.-


type alias User  =
   { name: String
   , email: String
   }

jsonDecUser : Json.Decode.Decoder ( User )
jsonDecUser =
   ("name" := Json.Decode.string) >>= \pname ->
   ("email" := Json.Decode.string) >>= \pemail ->
   Json.Decode.succeed {name = pname, email = pemail}

2.-


type alias Email = String
type alias User  =
   { name: String
   , email: Email
   }

jsonDecEmail : Json.Decode.Decoder String
jsonDecEmail = Json.Decode.string

jsonDecUser : Json.Decode.Decoder ( User )
jsonDecUser =
   ("name" := Json.Decode.string) >>= \pname ->
   ("email" := jsonDecEmail) >>= \pemail ->
   Json.Decode.succeed {name = pname, email = pemail}
bartavelle commented 6 years ago

Alright, do you mind testing the latest patch (commit a1b610637f0ba874113ad8743d4add912d35bcb3) ?

paparga commented 6 years ago

I did some testing:


data EmailT 
type Email = Tagged EmailT String

data User1
    = User1
    { name1 :: String
    , email1 :: Tagged EmailT String
    } deriving (Show, Eq)

data User2
    = User2
    { name2 :: String
    , email2 :: Email
    } deriving (Show, Eq)

User1 works

type alias User1  =
   { name1: String
   , email1: String
   }

jsonDecUser1 : Json.Decode.Decoder ( User1 )
jsonDecUser1 =
   ("name1" := Json.Decode.string) >>= \pname1 ->
   ("email1" := Json.Decode.string) >>= \pemail1 ->
   Json.Decode.succeed {name1 = pname1, email1 = pemail1}

jsonEncUser1 : User1 -> Value
jsonEncUser1  val =
   Json.Encode.object
   [ ("name1", Json.Encode.string val.name1)
   , ("email1", Json.Encode.string val.email1)
   ]

But User2 don't

type alias User2  =
   { name2: String
   , email2: Email
   }

jsonDecUser2 : Json.Decode.Decoder ( User2 )
jsonDecUser2 =
   ("name2" := Json.Decode.string) >>= \pname2 ->
   ("email2" := jsonDecEmail) >>= \pemail2 ->
   Json.Decode.succeed {name2 = pname2, email2 = pemail2}

jsonEncUser2 : User2 -> Value
jsonEncUser2  val =
   Json.Encode.object
   [ ("name2", Json.Encode.string val.name2)
   , ("email2", jsonEncEmail val.email2)
   ]
bartavelle commented 6 years ago

Yes, type aliases are not supported yet, and you can't derive something on them specifically!

You can support them by either:

paparga commented 6 years ago

Ok! I will close this issue.

Thanks!

bartavelle commented 6 years ago

(in theory it would be possible to handle the type alias case too, but it is a bit more work, and the problem si that you can't define how you would like it to be encoded on the Elm side with the current framework)

bartavelle commented 6 years ago

Let me know if you require an upload on hackage, or if you are fine with using the git master for now.

paparga commented 6 years ago

I'm fine with git and stack for now.

If you need help for implementing type alias, like documentation or testing just ping me. I've never done template haskell before, but maybe I could also help there.

Thanks for your time!