Comments (14)
I'm happy to tackle this too after #106 is settled maybe.
I'm assuming:
- Set, HashSet <=> TArray
- ByteString <=> TText
- Natural, Word <=> TInteger
- Float <=> TDouble
from tomland.
@jiegillet You're very close to the truth!
Natural, Word <=> TInteger
Float <=> TDouble
The above combinators are fine 👍
ByteString <=> TText
The types are true. But this should be done carefully since not every ByteString
can be converted to Text
.
Set, HashSet <=> TArray
Probably, should wait for this one. Currently we don't even have combinator for the list. After we have list, we can implement Set
and HashSet
trivially.
from tomland.
Got it. I'll be careful with the ByteString and I'll think about lists for a bit.
from tomland.
I've thought for a bit, and (sorry) my typeclass idea showed up again.
Here is what I have in mind
class Valuable a where
toValue :: a -> Maybe AnyValue
matchValue :: AnyValue -> Maybe a
_Valuable :: BiMap AnyValue a
_Valuable = BiMap matchValue toValue
instance Valuable Bool where
toValue = Just . AnyValue . Bool
matchValue (AnyValue t) = matchBool t
instance (Valuable a) => Valuable [a] where
toValue = mapM toValue >=> fmap AnyValue . toMArray
matchValue (AnyValue v) = matchArray matchValue v
_Bool :: BiMap AnyValue Bool
_Bool = _Valuable
_List :: Valuable a => BiMap AnyValue [a]
_List = _Valuable
It compiles and I think it's very easy to read and write. What do you think?
BTW, I just want to say that toMArray
has an awesome implementation, I was struggling to implement something like that before I realized it was already there.
EDIT:
And one helpful function
_BiMapVia :: Valuable m => (a -> Maybe m) -> (m -> Maybe a) -> BiMap AnyValue a
_BiMapVia toVal fromVal = _Valuable >>> BiMap fromVal toVal
from tomland.
@jiegillet In that case Valuable
doesn't really decreases amount of work. You still write implementation for every conversion function, just put it into typeclass.
Re _BiMapVia
: it's very rare case to have two functions with return values Maybe
. So we end having several different combinators... But more importantly, you don't really need BiMapVia
. Instead of passing two functions of types a -> Maybe m
and m -> Maybe a
you can just create BiMap a v
and compose it with _Text
or _Integer
or any other terminal combinator.
One thing that is hard to write with typeclass-based solution is the following function:
_Value :: (a -> Value t) -> (Value t -> a) -> BiMap a (Value t)
With such function you can guarantee that tag t
is the same in both directions. So the following won't typecheck:
_Value Integer fromText
It's hard to encode this with typeclasses if you have separate functions for converting in every direction.
BTW, I just want to say that toMArray has an awesome implementation, I was struggling to implement something like that before I realized it was already there
Thank you very much for the kind words ❤️ We decided to use GADTs
in this library to introduce more typesafety to the internal types. But this involves some dependent-type programming and theorem proving, so some functions are a bit hard to write...
from tomland.
OK, I think I understand better, thank you for explaining again. I have barely used GADTs before, I can understand some code fine, but I don't have an intuition for what they do and cannot do versus compared to typeclasses.
I agree that it doesn't decrease the amount of work, but it does let you write _List
easily :)
I guess we need to use _Array
then (which I think should be renamed _List
since we are giving names based on the concrete types BiMap
s encode). I can use it to make _Set
and _HashSet
then, something like _Set :: BiMap a AnyValue -> BiMap (Set a) AnyValue
.
from tomland.
I agree that it doesn't decrease the amount of work, but it does let you write _List easily :)
The problem with List
currently is that it's not possible with tomland
to encode list of custom user data types (and Set and HashSet as a consequence). With _Array
you can only have list of primitive types (Int, Double, Text).
from tomland.
You can have more than (Int, Double, Text):
_ShowArray :: (Show a, Read a) => BiMap AnyValue [a]
_ShowArray = _Array _Show
It compiles fine.
from tomland.
I think _Set
is not an issue:
_Set :: (Ord a) => BiMap AnyValue a -> BiMap AnyValue (S.Set a)
_Set bimap = _Array bimap >>> BiMap (Just . S.fromList) (Just . S.toList)
_ HashSet
is more tricky
_HashMap :: (Eq k, Hashable k) => BiMap AnyValue (k, v) -> BiMap AnyValue (H.HashMap k v)
_HashMap bimap = _Array bimap >>> BiMap (Just . H.fromList) (Just . H.toList)
because we can't create BiMap AnyValue (k, v)
easily. Unless we require Show k, Show v, Read k, Read v
, then (k, v)
can be inputed via _Show
.
from tomland.
@jiegillet Yeah, delegating to Read
and Show
is a possible option. But it's very slow solution. And, in that case, why TOML and not just store Read/Show
version of Haskell data structure in the file? 🙂
from tomland.
Agreed, it's a terrible solution.
Is there a way to do something like
data TValue = TBool | ... | TPair TValue TValue
data Value (t :: TValue) where
Pair :: Value t1 -> Value t2 -> Value (TPair t1 t2)
Again. Very limited experience with GADTs, sorry if it's not possible.
EDIT: seems to work, I'm having trouble defining sameValue
though. I'll keep thinking.
from tomland.
Is there a way to do something like
Yeah, it's possible, but usefulness of this definition is quite limitied. TValue
and Value
should represent exactly the TOML specification, and TOML doesn't have pairs. But it's definitely possible! sameValue
for this case might be tricky, that's true.
from tomland.
After many experimentation I managed to do it (I know it's not useful for tomland
it's just for fun at this point):
sameValue (Pair a1 b1) (Pair a2 b2)
= apply <$> (apply Refl <$> sameValue a1 a2) <*> sameValue b1 b2
The weakness is that if both values in the pair are mismatched, I only get one TypeMismatchError
in the resulting Left
. Anyway.
Oh my gosh, I realize now that I was supposed to implement _HashSet
and I did _HashMap
. My bad.
_HashSet :: (Eq a, Hashable a) => BiMap AnyValue a -> BiMap AnyValue (H.HashSet a)
_HashSet bimap = _Array bimap >>> BiMap (Just . H.fromList) (Just . H.toList)
One problem I realized by looking at the TOML specifications is that [["a", "b"], [1, 2]]
is a valid TOML array, although it cannot be a valid Haskell list. Have you thought at what to do about that?
from tomland.
One problem I realized by looking at the TOML specifications is that [["a", "b"], [1, 2]] is a valid TOML array, although it cannot be a valid Haskell list. Have you thought at what to do about that?
Yes, I actually thought about that when I've implemented bidirectional conversion first time! You can see my thoughts here:
I still don't see good usage of such arrays in Haskell, but it may arise in future.
from tomland.
Related Issues (20)
- Property-based tests generate invalid TOML keys occasionally HOT 3
- Profunctor of `Codec` can use some generalization. HOT 1
- Arrays of Arrays of Tables
- Failing build on Hackage HOT 2
- Compatibility with GHC 9.2 HOT 1
- change the key of a codec
- Test failure in test/Test/Toml/Codec/Combinator/Common.hs:39:5
- Top-level Tables HOT 3
- Compatibility with mtl-2.3 HOT 2
- Encodes unicode characters with double backslash
- How to parse a primitive type to a more constrained type? e.g. how to parse an 'IP' from a text field? HOT 5
- Compatibility with GHC 9.4 HOT 5
- Prepare release 1.3.3.2
- Support GHC 9.6 HOT 2
- Please make Hackage revision HOT 3
- Generic codec for Map should accept tables
- Wrong parsing of quotes
- Bump time dependency to < 1.15 HOT 2
- Dynamic Keys into `Map Text X` by
- Add to stackage? HOT 5
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from tomland.