elm-bridge 0.5.2 → 0.6.0
raw patch · 12 files changed
+104/−98 lines, 12 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Elm.TyRep: data ETCon
- Elm.TyRep: data ETVar
- Elm.Versions: Elm0p18 :: ElmVersion
+ Elm.TyRep: newtype ETCon
+ Elm.TyRep: newtype ETVar
+ Elm.Versions: Elm0p19 :: ElmVersion
Files
- CHANGELOG.md +4/−0
- README.md +1/−1
- elm-bridge.cabal +1/−1
- src/Elm/Derive.hs +17/−17
- src/Elm/Json.hs +6/−7
- src/Elm/Module.hs +18/−17
- src/Elm/TyRender.hs +9/−9
- src/Elm/TyRep.hs +18/−17
- src/Elm/Utils.hs +2/−2
- src/Elm/Versions.hs +3/−2
- test/Elm/JsonSpec.hs +14/−14
- test/Elm/ModuleSpec.hs +11/−11
CHANGELOG.md view
@@ -1,3 +1,7 @@+# v0.6.0++ * Support for Elm 0.19 + # v0.5.2 * Fix a bug about tuples.
README.md view
@@ -11,7 +11,7 @@ Building the bridge from [Haskell](http://haskell.org) to [Elm](http://elm-lang.org) and back. Define types once, use on both sides and enjoy easy (de)serialisation. Cheers! -This version of the package only supports Elm 0.18. Version 0.3.0.2 supports Elm 0.16 and Elm 0.17.+This version of the package only supports Elm 0.19. Version 0.5.2 supports Elm 0.18, and Version 0.3.0.2 supports Elm 0.16 and Elm 0.17. Note that the [bartavelle/json-helpers](http://package.elm-lang.org/packages/bartavelle/json-helpers/latest/) package, with version >= 1.2.0, is expected by the generated Elm modules.
elm-bridge.cabal view
@@ -1,5 +1,5 @@ name: elm-bridge-version: 0.5.2+version: 0.6.0 synopsis: Derive Elm types and Json code from Haskell types, using aeson's options description: Building the bridge from Haskell to Elm and back. Define types once, and derive the aeson and elm functions at the same time, using any aeson
src/Elm/Derive.hs view
@@ -1,6 +1,6 @@-{-# LANGUAGE CPP #-}+{-# LANGUAGE CPP #-} {-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE TupleSections #-}+{-# LANGUAGE TupleSections #-} {-| This module should be used to derive the Elm instance alongside the JSON ones. The prefered usage is to convert statements such as : @@ -26,16 +26,16 @@ ) where -import Elm.TyRep+import Elm.TyRep -import Control.Monad-import Data.Aeson.TH (deriveJSON, SumEncoding(..))-import qualified Data.Aeson.TH as A-import Language.Haskell.TH-import Language.Haskell.TH.Syntax-import Data.Char (toLower)-import Control.Applicative-import Prelude+import Control.Applicative+import Control.Monad+import Data.Aeson.TH (SumEncoding (..), deriveJSON)+import qualified Data.Aeson.TH as A+import Data.Char (toLower)+import Language.Haskell.TH+import Language.Haskell.TH.Syntax+import Prelude -- | Note that This default set of options is distinct from that in -- the @aeson@ package.@@ -51,7 +51,7 @@ } unwrapUnaryRecords :: A.Options -> Bool-unwrapUnaryRecords opts = A.unwrapUnaryRecords opts+unwrapUnaryRecords = A.unwrapUnaryRecords {-| This generates a default set of options. The parameter represents the number of characters that must be dropped from the Haskell field names.@@ -67,7 +67,7 @@ defaultOptionsDropLower :: Int -> A.Options defaultOptionsDropLower n = defaultOptions { A.fieldLabelModifier = lower . drop n } where- lower "" = ""+ lower "" = "" lower (x:xs) = toLower x : xs compileType :: Type -> Q Exp@@ -89,10 +89,10 @@ optSumType :: SumEncoding -> Q Exp optSumType se = case se of- TwoElemArray -> [|SumEncoding' TwoElemArray|]+ TwoElemArray -> [|SumEncoding' TwoElemArray|] ObjectWithSingleField -> [|SumEncoding' ObjectWithSingleField|]- TaggedObject tn cn -> [|SumEncoding' (TaggedObject tn cn)|]- UntaggedValue -> [|SumEncoding' UntaggedValue|]+ TaggedObject tn cn -> [|SumEncoding' (TaggedObject tn cn)|]+ UntaggedValue -> [|SumEncoding' UntaggedValue|] runDerive :: Name -> [TyVarBndr] -> (Q Exp -> Q Exp) -> Q [Dec] runDerive name vars mkBody =@@ -122,7 +122,7 @@ argNames = flip map vars $ \v -> case v of- PlainTV tv -> tv+ PlainTV tv -> tv KindedTV tv _ -> tv deriveAlias :: Bool -> A.Options -> Name -> [TyVarBndr] -> [VarStrictType] -> Q [Dec]
src/Elm/Json.hs view
@@ -14,11 +14,10 @@ ) where -import Data.List-import Data.Aeson.Types (SumEncoding(..))--import Elm.TyRep-import Elm.Utils+import Data.Aeson.Types (SumEncoding (..))+import Data.List+import Elm.TyRep+import Elm.Utils data MaybeHandling = Root | Leaf deriving Eq@@ -29,7 +28,7 @@ isOption :: EType -> Bool isOption (ETyApp (ETyCon (ETCon "Maybe")) _) = True-isOption _ = False+isOption _ = False jsonParserForType' :: MaybeHandling -> EType -> String jsonParserForType' mh ty =@@ -208,7 +207,7 @@ ++ "\n ]\n" ETypeSum (ESum name opts (SumEncoding' se) _ unarystring) -> case allUnaries unarystring opts of- Nothing -> defaultEncoding opts+ Nothing -> defaultEncoding opts Just strs -> unaryEncoding strs where encodeFunction = case se of
src/Elm/Module.hs view
@@ -1,19 +1,19 @@ {-# LANGUAGE ExistentialQuantification #-}-{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE ScopedTypeVariables #-} {-| Functions in this module are used to generate Elm modules. Note that the generated modules depend on the @bartavelle/json-helpers@ package. -} module Elm.Module where -import Data.Proxy-import Data.List-import Control.Arrow (second)+import Control.Arrow (second)+import Data.List+import Data.Proxy -import Elm.TyRep-import Elm.TyRender-import Elm.Json-import Elm.Versions+import Elm.Json+import Elm.TyRender+import Elm.TyRep+import Elm.Versions -- | Existential quantification wrapper for lists of type definitions data DefineElm@@ -23,7 +23,7 @@ moduleHeader :: ElmVersion -> String -> String-moduleHeader Elm0p18 moduleName = "module " ++ moduleName ++ " exposing(..)"+moduleHeader _ moduleName = "module " ++ moduleName ++ " exposing(..)" -- | Creates an Elm module for the given version. This will use the default -- type conversion rules (to -- convert @Vector@ to @List@, @HashMap a b@@@ -32,7 +32,7 @@ -> String -- ^ Module name -> [DefineElm] -- ^ List of definitions to be included in the module -> String-makeElmModuleWithVersion elmVersion moduleName defs = unlines (+makeElmModuleWithVersion elmVersion moduleName defs = unlines [ moduleHeader elmVersion moduleName , "" , "import Json.Decode"@@ -43,14 +43,16 @@ , "import Set exposing (Set)" , "" , ""- ]) ++ makeModuleContent defs+ ] ++ makeModuleContent defs -- | Creates an Elm module. This will use the default type conversion rules (to -- convert @Vector@ to @List@, @HashMap a b@ to @List (a,b)@, etc.).+--+-- default to 0.19 makeElmModule :: String -- ^ Module name -> [DefineElm] -- ^ List of definitions to be included in the module -> String-makeElmModule = makeElmModuleWithVersion Elm0p18+makeElmModule = makeElmModuleWithVersion Elm0p19 -- | Generates the content of a module. You will be responsible for -- including the required Elm headers. This uses the default type@@ -84,9 +86,9 @@ alterTypes :: SumTypeConstructor -> SumTypeConstructor alterTypes (STC cn dn s) = STC cn dn $ case s of Anonymous flds -> Anonymous (map f' flds)- Named flds -> Named (map (second f') flds)+ Named flds -> Named (map (second f') flds) f' (ETyApp a b) = f (ETyApp (f' a) (f' b))- f' x = f x+ f' x = f x -- | Given a list of type names, will @newtype@ all the matching type -- definitions.@@ -128,12 +130,11 @@ _ -> t where isString (ETyCon (ETCon "String")) = True- isString _ = False+ isString _ = False isComparable (ETyCon (ETCon n)) = n `elem` ["String", "Int"]- isComparable _ = False -- TODO check what Elm actually uses+ isComparable _ = False -- TODO check what Elm actually uses tc = ETyCon . ETCon checkMap k v | isString k = ETyApp (ETyApp (tc "Dict") k) v | otherwise = ETyApp (tc "List") (ETyApp (ETyApp (ETyTuple 2) k) v) checkSet s | isComparable s = ETyApp (ETyCon (ETCon "Set")) s | otherwise = ETyApp (ETyCon (ETCon "List")) s-
src/Elm/TyRender.hs view
@@ -1,10 +1,10 @@ {-| This module should not usually be imported. -} module Elm.TyRender where -import Elm.TyRep-import Elm.Utils+import Elm.TyRep+import Elm.Utils -import Data.List+import Data.List class ElmRenderable a where renderElm :: a -> String@@ -12,22 +12,22 @@ instance ElmRenderable ETypeDef where renderElm td = case td of- ETypeAlias alias -> renderElm alias- ETypeSum s -> renderElm s+ ETypeAlias alias -> renderElm alias+ ETypeSum s -> renderElm s ETypePrimAlias pa -> renderElm pa instance ElmRenderable EType where renderElm ty = case unpackTupleType ty of [t] -> renderSingleTy t- xs -> "(" ++ intercalate ", " (map renderSingleTy xs) ++ ")"+ xs -> "(" ++ intercalate ", " (map renderSingleTy xs) ++ ")" where renderApp (ETyApp l r) = renderApp l ++ " " ++ renderElm r- renderApp x = renderElm x+ renderApp x = renderElm x renderSingleTy typ = case typ of- ETyVar v -> renderElm v- ETyCon c -> renderElm c+ ETyVar v -> renderElm v+ ETyCon c -> renderElm c ETyTuple _ -> error "Library Bug: This should never happen!" ETyApp l r -> "(" ++ renderApp l ++ " " ++ renderElm r ++ ")"
src/Elm/TyRep.hs view
@@ -3,13 +3,14 @@ -} module Elm.TyRep where -import Data.List-import Data.Proxy-import Data.Typeable (Typeable, TyCon, TypeRep, splitTyConApp, tyConName, typeRep, typeRepTyCon)+import Data.List+import Data.Proxy+import Data.Typeable (TyCon, TypeRep, Typeable, splitTyConApp,+ tyConName, typeRep, typeRepTyCon) -import Data.Aeson.Types (SumEncoding(..))-import Data.Monoid ((<>))-import Data.Maybe (fromMaybe)+import Data.Aeson.Types (SumEncoding (..))+import Data.Maybe (fromMaybe)+import Data.Monoid ((<>)) -- | Type definition, including constructors. data ETypeDef@@ -31,7 +32,7 @@ > ETCon "Int" -}-data ETCon+newtype ETCon = ETCon { tc_name :: String } deriving (Show, Eq, Ord)@@ -40,7 +41,7 @@ > ETVar "a" -}-data ETVar+newtype ETVar = ETVar { tv_name :: String } deriving (Show, Eq, Ord)@@ -64,10 +65,10 @@ data EAlias = EAlias- { ea_name :: ETypeName- , ea_fields :: [(String, EType)]- , ea_omit_null :: Bool- , ea_newtype :: Bool+ { ea_name :: ETypeName+ , ea_fields :: [(String, EType)]+ , ea_omit_null :: Bool+ , ea_newtype :: Bool , ea_unwrap_unary :: Bool } deriving (Show, Eq, Ord) @@ -80,7 +81,7 @@ isNamed s = case s of Named _ -> True- _ -> False+ _ -> False data SumTypeConstructor = STC@@ -88,7 +89,7 @@ , _stcEncoded :: String , _stcFields :: SumTypeFields } deriving (Show, Eq, Ord)- + data ESum = ESum { es_name :: ETypeName@@ -170,10 +171,10 @@ toElmType' :: TypeRep -> EType toElmType' rep -- String (A list of Char)- | con == (typeRepTyCon $ typeRep (Proxy :: Proxy [])) &&+ | con == typeRepTyCon (typeRep (Proxy :: Proxy [])) && args == [typeRep (Proxy :: Proxy Char)] = ETyCon (ETCon "String") -- List is special because the constructor name is [] in Haskell and List in elm- | con == (typeRepTyCon $ typeRep (Proxy :: Proxy [])) = ETyApp (ETyCon $ ETCon $ "List") (toElmType' (head args))+ | con == typeRepTyCon (typeRep (Proxy :: Proxy [])) = ETyApp (ETyCon $ ETCon "List") (toElmType' (head args)) -- The unit type '()' is a 0-ary tuple. | isTuple $ tyConName con = foldl ETyApp (ETyTuple $ length args) $ map toElmType' args | otherwise = typeApplication con args@@ -185,7 +186,7 @@ where isTuple' :: String -> Bool isTuple' (')':xs') = all (== ',') xs'- isTuple' _ = False+ isTuple' _ = False isTuple _ = False typeApplication :: TyCon -> [TypeRep] -> EType
src/Elm/Utils.hs view
@@ -1,9 +1,9 @@ module Elm.Utils where -import Data.Char (toUpper)+import Data.Char (toUpper) cap :: String -> String-cap "" = ""+cap "" = "" cap (x:xs) = toUpper x : xs fixReserved :: String -> String
src/Elm/Versions.hs view
@@ -1,8 +1,9 @@ {-| A type to represent versions of Elm for produced code to work against. -This module ONLY supports Elm 0.18+ This module only supports Elm 0.19.x !!! -} module Elm.Versions where data ElmVersion- = Elm0p18+ = Elm0p19+
test/Elm/JsonSpec.hs view
@@ -1,30 +1,30 @@ {-# LANGUAGE TemplateHaskell #-} module Elm.JsonSpec (spec) where -import Elm.Derive-import Elm.TyRender-import Elm.TyRep-import Elm.Json+import Elm.Derive+import Elm.Json+import Elm.TyRender+import Elm.TyRep -import Data.Proxy-import Test.Hspec-import Data.Char (toLower)-import Data.Aeson.Types (defaultTaggedObject)-import qualified Data.Map.Strict as M-import qualified Data.Aeson.TH as TH+import qualified Data.Aeson.TH as TH+import Data.Aeson.Types (defaultTaggedObject)+import Data.Char (toLower)+import qualified Data.Map.Strict as M+import Data.Proxy+import Test.Hspec data Foo = Foo- { f_name :: String+ { f_name :: String , f_blablub :: Int } deriving (Show, Eq) data Bar a = Bar- { b_name :: a+ { b_name :: a , b_blablub :: Int- , b_tuple :: (Int, String)- , b_list :: [Bool]+ , b_tuple :: (Int, String)+ , b_list :: [Bool] } deriving (Show, Eq) data SomeOpts a
test/Elm/ModuleSpec.hs view
@@ -26,7 +26,7 @@ $(deriveElmDef (defaultOptionsDropLower 5) ''Qux) moduleHeader' :: ElmVersion -> String -> String-moduleHeader' Elm0p18 name = "module " ++ name ++ " exposing(..)"+moduleHeader' Elm0p19 name = "module " ++ name ++ " exposing(..)" moduleCode :: ElmVersion -> String moduleCode elmVersion = unlines@@ -105,7 +105,7 @@ spec :: Spec spec = do makeElmModuleSpec- version0p18Spec+ version0p19Spec makeElmModuleSpec :: Spec makeElmModuleSpec =@@ -113,14 +113,14 @@ it "should produce the correct code" $ do let modu = makeElmModule "Foo" [DefineElm (Proxy :: Proxy (Bar a))] let modu' = makeElmModule "Qux" [DefineElm (Proxy :: Proxy (Qux a))]- modu `shouldBe` (moduleCode Elm0p18)- modu' `shouldBe` (moduleCode' Elm0p18)+ modu `shouldBe` moduleCode Elm0p19+ modu' `shouldBe` moduleCode' Elm0p19 -version0p18Spec :: Spec-version0p18Spec =- describe "makeElmModuleWithVersion Elm0p18" $+version0p19Spec :: Spec+version0p19Spec =+ describe "makeElmModuleWithVersion Elm0p19" $ it "should produce the correct code" $- do let modu = makeElmModuleWithVersion Elm0p18 "Foo" [DefineElm (Proxy :: Proxy (Bar a))]- let modu' = makeElmModuleWithVersion Elm0p18 "Qux" [DefineElm (Proxy :: Proxy (Qux a))]- modu `shouldBe` (moduleCode Elm0p18)- modu' `shouldBe` (moduleCode' Elm0p18)+ do let modu = makeElmModuleWithVersion Elm0p19 "Foo" [DefineElm (Proxy :: Proxy (Bar a))]+ let modu' = makeElmModuleWithVersion Elm0p19 "Qux" [DefineElm (Proxy :: Proxy (Qux a))]+ modu `shouldBe` moduleCode Elm0p19+ modu' `shouldBe` moduleCode' Elm0p19