sras / elminator

Generate Elm type definitions and json encoders/decoders from Haskell types.
BSD 3-Clause "New" or "Revised" License
27 stars 1 forks source link

decoder uses `encodeP` instead of `decodeP` for unknown type `P` #1

Closed bmillwood closed 2 months ago

bmillwood commented 1 year ago

My reproduction:

GenSrc.hs:

{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingStrategies #-}
module GenSrc where

import GHC.Generics (Generic)

import qualified Elminator as Elm

data P = PC
  deriving stock (Generic)

data T = TC P
  deriving stock (Generic)
  deriving anyclass (Elm.ToHType)

Main.hs:

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeApplications #-}
module Main where

import qualified Data.Aeson as Aeson
import Data.Proxy (Proxy (Proxy))
import Data.Text (Text)
import qualified Data.Text.IO as Text
import qualified Elminator as Elm

import GenSrc

main :: IO ()
main = Text.putStrLn generatedCode

generatedCode :: Text
generatedCode =
  $(Elm.generateFor Elm.Elm0p19 Aeson.defaultOptions "Gen" (Just "Gen.elm") $ do
    Elm.include (Proxy @T) (Elm.Everything Elm.Poly)
  )

produces the following Gen.elm:

module Gen exposing (..)

import Json.Encode as E
import Json.Decode as D

seqApp : D.Decoder (a1 -> v) -> D.Decoder a1 -> D.Decoder v
seqApp inDec oDec =
  let
    mapFn v = D.map (\x -> x v) inDec
  in D.andThen mapFn oDec

elminatorEncodeList0p19 : (a -> E.Value)-> List a -> E.Value
elminatorEncodeList0p19 fn ls = E.list fn ls

encodeMaybe : (a -> E.Value)-> Maybe a -> E.Value
encodeMaybe fn ma = case ma of
  Just a -> fn a
  Nothing -> E.null

type T = TC P

encodeT : T  -> E.Value
encodeT a = 
 case a of
  TC a1 -> encodeP (a1)

decodeT : D.Decoder T 
decodeT  = 
 D.oneOf ([ D.map (TC) (encodeP)])

In particular, note that both encodeT and decodeT use encodeChar.

This issue goes away if I derive ToHType for P, but in my actual code P is Char so I can't derive ToHType for it. It'd be nice to support Char natively, but in the absence of that, I'd like to at least be able to supply my own encodeChar and decodeChar functions to make the generated code work, but since they're both encodeChar, I can't. (I'd also need the ability to bring them into scope here, but my current solution to that is just manually adding imports after code generation.)

bmillwood commented 1 year ago

(In fact this is even visible in the example in the README example)

sras commented 2 months ago

@bmillwood Thanks for reporting the issue.