Skip to content

Commit bd8c688

Browse files
author
Antonio Alonso Dominguez
committed
initial import
0 parents  commit bd8c688

12 files changed

+342
-0
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.stack-work/
2+
hexomorph.cabal
3+
*~

ChangeLog.md

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Changelog for hexomorph
2+
3+
## Unreleased changes

LICENSE

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
Copyright Author name here (c) 2018
2+
3+
All rights reserved.
4+
5+
Redistribution and use in source and binary forms, with or without
6+
modification, are permitted provided that the following conditions are met:
7+
8+
* Redistributions of source code must retain the above copyright
9+
notice, this list of conditions and the following disclaimer.
10+
11+
* Redistributions in binary form must reproduce the above
12+
copyright notice, this list of conditions and the following
13+
disclaimer in the documentation and/or other materials provided
14+
with the distribution.
15+
16+
* Neither the name of Author name here nor the names of other
17+
contributors may be used to endorse or promote products derived
18+
from this software without specific prior written permission.
19+
20+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24+
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26+
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28+
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# hexomorph

Setup.hs

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import Distribution.Simple
2+
main = defaultMain

package.yaml

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
name: hexomorph
2+
version: 0.1.0.0
3+
github: "githubuser/hexomorph"
4+
license: BSD3
5+
author: "Author name here"
6+
maintainer: "[email protected]"
7+
copyright: "2018 Author name here"
8+
9+
extra-source-files:
10+
- README.md
11+
- ChangeLog.md
12+
13+
# Metadata used when publishing your package
14+
# synopsis: Short description of your package
15+
# category: Web
16+
17+
# To avoid duplicated efforts in documentation and dealing with the
18+
# complications of embedding Haddock markup inside cabal files, it is
19+
# common to point users to the README.md file.
20+
description: Please see the README on GitHub at <https://github.com/githubuser/hexomorph#readme>
21+
22+
dependencies:
23+
- aeson
24+
- base >= 4.7 && < 5
25+
- mtl
26+
- natural-transformation
27+
- lens
28+
- free
29+
- text
30+
- time
31+
- unordered-containers
32+
- vector
33+
34+
library:
35+
source-dirs: src
36+
37+
tests:
38+
hexomorph-test:
39+
main: Spec.hs
40+
source-dirs: test
41+
ghc-options:
42+
- -threaded
43+
- -rtsopts
44+
- -with-rtsopts=-N
45+
dependencies:
46+
- hexomorph

src/Data/Schema.hs

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module Data.Schema
2+
( module Data.Schema.JSON
3+
, module Data.Schema.Types
4+
) where
5+
6+
import Data.Schema.JSON
7+
import Data.Schema.Types

src/Data/Schema/JSON.hs

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
{-# LANGUAGE GADTs #-}
2+
{-# LANGUAGE OverloadedStrings #-}
3+
{-# LANGUAGE ExistentialQuantification #-}
4+
5+
module Data.Schema.JSON
6+
( serializer
7+
, deserializer
8+
) where
9+
10+
import Data.Aeson (parseJSON)
11+
import qualified Data.Aeson as Json
12+
import qualified Data.Aeson.Types as Json
13+
import Data.Schema.Types
14+
import Control.Applicative.Free
15+
import Control.Lens
16+
import Control.Monad.State (State)
17+
import qualified Control.Monad.State as ST
18+
import Data.HashMap.Strict (HashMap)
19+
import qualified Data.HashMap.Strict as Map
20+
import Data.Text (Text)
21+
22+
serializer :: Serializer a Json.Value
23+
serializer IntSchema = Json.Number . fromIntegral
24+
serializer BoolSchema = Json.Bool
25+
serializer StringSchema = Json.String
26+
serializer (ListSchema s) = \a -> Json.Array $ fmap (serializer s) a
27+
serializer (RecordSchema ps) = \value -> Json.Object $ ST.execState (runAp (step value) ps) Map.empty
28+
where step :: o -> PropDef o v -> State (HashMap Text Json.Value) v
29+
step obj (PropDef name schema getter) = do
30+
let el = view getter obj
31+
ST.modify $ Map.insert name (serializer schema $ el)
32+
return el
33+
serializer (UnionSchema alts) = undefined
34+
35+
deserializer :: Schema a -> (Json.Value -> Json.Parser a)
36+
deserializer IntSchema = parseJSON
37+
deserializer BoolSchema = parseJSON
38+
deserializer StringSchema = parseJSON
39+
deserializer (ListSchema s) = \json -> case json of
40+
Json.Array v -> traverse (deserializer s) v
41+
other -> fail $ "Expected a JSON array but got: " ++ (show other)
42+
deserializer (RecordSchema ps) = \json -> case json of
43+
Json.Object obj -> runAp (step obj) ps
44+
where step :: HashMap Text Json.Value -> PropDef o v -> Json.Parser v
45+
step jsonObj (PropDef name schema _) =
46+
Json.explicitParseField (\v -> deserializer schema $ v) jsonObj name
47+
other -> fail $ "Expected JSON Object but got: " ++ (show other)
48+
deserializer (UnionSchema alts) = undefined

src/Data/Schema/Types.hs

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
{-# LANGUAGE GADTs #-}
2+
{-# LANGUAGE RankNTypes #-}
3+
4+
module Data.Schema.Types where
5+
6+
import Control.Applicative.Free
7+
import Control.Lens
8+
import Data.Text (Text)
9+
import qualified Data.Text as T
10+
import Data.Vector (Vector)
11+
12+
data PropDef o a = PropDef
13+
{ propName :: Text
14+
, propSchema :: Schema a
15+
, propAccessor :: Getter o a
16+
}
17+
18+
type Props o = Ap (PropDef o) o
19+
20+
-- propDef :: Text -> Schema a -> Getter o a -> Props o
21+
-- propDef name schema get = liftAp $ ((PropDef name schema get) :: PropDef o a)
22+
23+
-- required :: PropDef o a -> Props o
24+
-- required = liftAp
25+
26+
--type Props a = Props' a a
27+
28+
-- emptyProps :: forall a. Props' a ()
29+
-- emptyProps = Pure ()
30+
31+
data Alt a = forall b. Alt
32+
{ altId :: Text
33+
, altSchema :: Schema b
34+
, altPrism :: Prism' a b
35+
}
36+
37+
data Schema a where
38+
IntSchema :: Schema Int
39+
BoolSchema :: Schema Bool
40+
StringSchema :: Schema Text
41+
NoSchema :: Schema ()
42+
ListSchema :: Schema a -> Schema (Vector a)
43+
RecordSchema :: Props o -> Schema o
44+
UnionSchema :: [Alt a] -> Schema a
45+
46+
-- voidGetter :: forall a. Getter a ()
47+
-- voidGetter = to (const ())
48+
49+
-- emptyRecord :: forall a. Schema a
50+
-- emptyRecord =
51+
-- let voidPropDef :: PropDef a ()
52+
-- voidPropDef = PropDef T.empty NoSchema voidGetter
53+
54+
-- lifted :: Props a
55+
-- lifted = liftAp voidPropDef
56+
-- in RecordSchema lifted
57+
58+
type Serializer a b = Schema a -> (a -> b)
59+
type Deserializer a b = Schema b -> (a -> Either String b)

src/Lib.hs

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
{-# LANGUAGE RankNTypes #-}
2+
{-# LANGUAGE DeriveFunctor #-}
3+
{-# LANGUAGE GADTs #-}
4+
{-# LANGUAGE TypeOperators #-}
5+
{-# LANGUAGE FlexibleContexts #-}
6+
{-# LANGUAGE OverloadedStrings #-}
7+
{-# LANGUAGE LambdaCase #-}
8+
9+
module Lib
10+
( someFunc
11+
) where
12+
13+
import Control.Applicative.Free
14+
import Control.Lens
15+
import Data.Schema
16+
import Data.Text (Text)
17+
import qualified Data.Text as T
18+
import Data.Time.Clock
19+
20+
stringIso :: Iso' String Text
21+
stringIso = iso T.pack T.unpack
22+
23+
data Role =
24+
UserRole UserRole
25+
| AdminRole AdminRole
26+
deriving (Eq, Show)
27+
28+
data UserRole = UserRole' { userName :: Text }
29+
deriving (Eq, Show)
30+
31+
data AdminRole = AdminRole' { department :: Text, subordinateCount :: Int }
32+
deriving (Eq, Show)
33+
34+
_UserRole :: Prism' Role UserRole
35+
_UserRole = prism' UserRole $ \case
36+
UserRole x -> Just x
37+
_ -> Nothing
38+
39+
_AdminRole :: Prism' Role AdminRole
40+
_AdminRole = prism' AdminRole $ \case
41+
AdminRole x -> Just x
42+
_ -> Nothing
43+
44+
adminDept :: Getter AdminRole Text
45+
adminDept = to department
46+
47+
subordinateCountGetter :: Getter AdminRole Int
48+
subordinateCountGetter = to subordinateCount
49+
50+
userNameProp = liftAp $ PropDef "name" StringSchema (to userName)
51+
userRoleAlt = Alt "user" (RecordSchema (UserRole' <$> userNameProp)) _UserRole
52+
53+
departmentProp = liftAp $ PropDef "department" StringSchema adminDept
54+
subordinateCountProp = liftAp $ PropDef "subordinateCount" IntSchema subordinateCountGetter
55+
adminRoleAlt = Alt "admin" (RecordSchema (AdminRole' <$> departmentProp <*> subordinateCountProp)) _AdminRole
56+
57+
userSchema :: Schema Role
58+
userSchema = UnionSchema [userRoleAlt, adminRoleAlt]
59+
60+
data Person1 = Person1 { aName :: String, aAge :: Int }
61+
62+
data Person = Person { name :: String, birthDate :: UTCTime, roles :: [Role] }
63+
64+
someFunc :: IO ()
65+
someFunc = putStrLn "someFunc"

stack.yaml

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# This file was automatically generated by 'stack init'
2+
#
3+
# Some commonly used options have been documented as comments in this file.
4+
# For advanced use and comprehensive documentation of the format, please see:
5+
# https://docs.haskellstack.org/en/stable/yaml_configuration/
6+
7+
# Resolver to choose a 'specific' stackage snapshot or a compiler version.
8+
# A snapshot resolver dictates the compiler version and the set of packages
9+
# to be used for project dependencies. For example:
10+
#
11+
# resolver: lts-3.5
12+
# resolver: nightly-2015-09-21
13+
# resolver: ghc-7.10.2
14+
# resolver: ghcjs-0.1.0_ghc-7.10.2
15+
#
16+
# The location of a snapshot can be provided as a file or url. Stack assumes
17+
# a snapshot provided as a file might change, whereas a url resource does not.
18+
#
19+
# resolver: ./custom-snapshot.yaml
20+
# resolver: https://example.com/snapshots/2018-01-01.yaml
21+
resolver: lts-11.13
22+
23+
# User packages to be built.
24+
# Various formats can be used as shown in the example below.
25+
#
26+
# packages:
27+
# - some-directory
28+
# - https://example.com/foo/bar/baz-0.0.2.tar.gz
29+
# - location:
30+
# git: https://github.com/commercialhaskell/stack.git
31+
# commit: e7b331f14bcffb8367cd58fbfc8b40ec7642100a
32+
# - location: https://github.com/commercialhaskell/stack/commit/e7b331f14bcffb8367cd58fbfc8b40ec7642100a
33+
# subdirs:
34+
# - auto-update
35+
# - wai
36+
packages:
37+
- .
38+
# Dependency packages to be pulled from upstream that are not in the resolver
39+
# using the same syntax as the packages field.
40+
# (e.g., acme-missiles-0.3)
41+
extra-deps: []
42+
# - category-extras-1.0.2
43+
# - categories-1.0.7
44+
# - comonad-extras-4.0
45+
# - comonad-transformers-4.0
46+
# - comonads-fd-4.0
47+
# - groupoids-4.0
48+
# - indexed-0.1.3
49+
# - indexed-extras-0.2
50+
# - profunctor-extras-4.0
51+
# - representable-functors-3.2.0.2
52+
# - representable-profunctors-3.2
53+
54+
# Override default flag values for local packages and extra-deps
55+
# flags: {}
56+
57+
# Extra package databases containing global packages
58+
# extra-package-dbs: []
59+
60+
# Control whether we use the GHC we find on the path
61+
# system-ghc: true
62+
#
63+
# Require a specific version of stack, using version ranges
64+
# require-stack-version: -any # Default
65+
# require-stack-version: ">=1.7"
66+
#
67+
# Override the architecture used by stack, especially useful on Windows
68+
# arch: i386
69+
# arch: x86_64
70+
#
71+
# Extra directories used by stack for building
72+
# extra-include-dirs: [/path/to/dir]
73+
# extra-lib-dirs: [/path/to/dir]
74+
#
75+
# Allow a newer minor version of GHC than the snapshot specifies
76+
# compiler-check: newer-minor

test/Spec.hs

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
main :: IO ()
2+
main = putStrLn "Test suite not yet implemented"

0 commit comments

Comments
 (0)