Fork me on GitHub
#malli
<
2021-06-01
>
docouto06:06:12

Any idea when the 'schema' branch could be merged into master?

docouto06:06:07

I mean, are there major things preventing this from happening?

Ben Sless14:06:59

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

Ben Sless15:06:54

map and and would be sort of product types?

nilern13:06:29

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.

nilern13:06:38

I would rather have something like mu/fmap than select-keys automagically working through maybe etc.

nilern13:06:42

(mu/fmap #(mu/select-keys % [:x]) [:maybe [:map [:x int?] [:y int?]]])
;=> [:maybe [:map [:x int?]]] 

Ben Sless14:06:50

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

Ben Sless14:06:45

And the reason I thought of Monads and not just Functors is cases like [:maybe [:maybe T]] which could be joined, and even hairier situations where you have some combinations of containers

Ben Sless14:06:22

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

nilern07:06:23

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...

Ben Sless07:06:30

> 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?

nilern09:06:54

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).

Ben Sless09:06:29

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 equivalent

nilern11:06:53

In 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.).

nilern11:06:22

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

Ben Sless12:06:18

You mean it can be behind a reference?

nilern09:06:47

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...