Any idea when the 'schema' branch could be merged into master?
I mean, are there major things preventing this from happening?
I hate to use the M word, but I think the answer to https://github.com/metosin/malli/issues/304 is yes. If we can say malli is working with types, aren't container schemas monads, of sorts? maybe is Maybe, or is Either, etc
I think Functor is more relevant than Monad here. tuple
is a product too, or
and some other things are sums. But still it is often not possible to jump to conclusions based on category or type theory.
I would rather have something like mu/fmap
than select-keys
automagically working through maybe
etc.
(mu/fmap #(mu/select-keys % [:x]) [:maybe [:map [:x int?] [:y int?]]])
;=> [:maybe [:map [:x int?]]]
I agree with the observation, but I think the answer is the other way around - select-keys
should work via fmap
instead of knowing the implementation details of the container it's operating on
And the reason I thought of Monads and not just Functors is cases like [:maybe [:maybe T]]
which could be join
ed, and even hairier situations where you have some combinations of containers
And if schemas are some representation of types, all the schema manipulations in malli.util
could be represented as type manipulations which are implemented by the schemas instead of being bespoke data manipulations
I especially hate it when you run through several layers automagically, like in Cats I think (fmap inc [(just 3) 2]) ;=> [(just 4) 3]
or something and JS Promises are not monads because .then
tries to be both bind
and (flipped) fmap
...
> anything automagically
I can't disagree with you there. These things should be explicit.
And yet, don't you think malli could benefit from abstracting schema manipulation and composition to interfaces of types manipulation and composition instead of data manipulation?
It lends itself to some weird phenomena, such as mu/get-in
in a maybe-schema requires explicit reference to the path, so in [:maybe [:map [:a int?]]]
int?
is in [0 :a]
. Is that the right way to go about it?
I haven't thought much about the schema manipulation stuff. But maybe the non-semantic (`[0 :a]` etc.) approach is not that bad and in fact kind of idiomatic. And I think even dependently typed languages like Idris will just pattern match on the type syntax even though it is much more against their philosophy (at least if the kind of the type is Type
). It is hard to say what feels right when there is so little prior art (that I am aware of).
There's stuff over in typed land which also seems like leaky implementation and not a correct design choice
T1 = A | B
T2 = C | T1
Is not equivalent to
T3 = A | B | C
because unions are tagged, although it's still just a union of sets of input fields. They should be equivalentIn a language with untagged unions those will be equivalent (or it is a bug). I don't really regard ADT:s as union types, especially since in most languages each variant can have multiple and even named fields. And you can also do something similar with structural variant types (e.g. OCaml) although as usual type inference complicates that (unification must work etc.).
By the way one reason lens types are hard is that not all containers have the contained things as type parameters e.g. data Point = Point {x : Int, y : Int}
clearly contains Int
:s but cannot be made a Functor
or otherwise extract that fact on the type level because it's just an opaque name like :point
You mean it can be behind a reference?
In SML it would be like a reference but in Haskell/OCaml/Java it is just an abstract type. Even If there was a way to get to the Int
part(s) it is different from functors where it is always the first argument and you also have to decide between x, y or both...
https://clojurians.slack.com/archives/CLDK6MFMK/p1623959758175200
map
and and
would be sort of product types?