crocks
crocks copied to clipboard
Formal API for creating new ADTs
First of all, impressive library! Really fun to work with.
I'd like to suggest making defineUnion part of the library's API. While there are other libraries that are specifically dedicated to creating new ADTs, the APIs you end up are quite different, which leads to inconsistencies in the code base. Some types are using one form of pattern matching, others use a different API.
What's missing (IMHO):
- Exporting defineUnion functionality
- Support for (de)serialising ADTs
I'm willing to provide a PR if the concept is deemed worthy.
Thanks for your kind words. So I have put a lot of thought into this and TBH, this is more a collection of ADT implementations. But boy oh boy there have been many times I just wanted a quick UnionType or to define some Ring for a data type specific to my domain, nothing really that could be used in the wild.
So in order to make this just a collection of known APIs, I am going to create a separate crocks-daggy
as daggy does custom ADTs (will also see how this going and make a more generic based on the others like folktale adt, uniontypes, etc) you just pass it your 🌽structor/TypeRep and it will add all the stuff needed to get it to work in the crocks ecosystem.
I think we could also support serialization/deserialization in another lib as opposed to baking it into the types themselves. In the past of have just created my own (de)serializers. But I am open to ideas.
What are your thoughts on separate packages?
Separate packages make perfect sense. The approach will provide users with more freedom and keep each package leaner.
I'd be happy to start the work on crocks-daggy
if you know what you want it to look like (or willing to start the discussion). I would like to migrate to crocks
and having the ability to create my own ADTs with the same API is a blocker for me.
Are you willing to entertain this suggestion?
Sorry it took so long to get back. Oh yeah I am always up to entertain suggestions such as these.
So I was thinking, it would be some function that took a daggy
definition and gave back a new definition with the following addtions:
-
the TypeRep has an
@@implements
function. This function is of the form() -> [ String ]
, and returns a list of the FL methods in non-prefix form, for example a Monoid Functor with Setoid would be:[ 'empty', 'equals', 'concat', 'map' ]
. (all TypeRep level functions should be reported, likeof
,empty
,zero
, etc). It will build this list based on the methods/functions of the provided daggy definition. -
a
@@type
String property needs to be present on both the TypeRep and the instance (prototype) and should include the daggy typename and be prefixed withcrocks-daggy
like so:crocks-daggy/[typename]
(Sanctuary Style) -
both the instance and TypeRef should have a
type
method that returns the String TypeNametype :: () -> String
-
All TypeRef functions should also appear as methods on the instance (prototype) in addition to the TypeRef,
empty
,of
, etc. -
All fantasy-land defined methods should have the function available in prefixed and non-prefixed names. For instance, if the original definition defines
map
on the prototype, thenfantasy-land/map
will be added to the prototype. We will just do this blindly, it is up to the user to make sure they have the propermap
defined. Another example: Given thatempty
was provided on the TypeRep,fantasy-land/empty
will be added to the TypeRep, andempty
andfantasy-land/empty
will be added to the instance (prototype) as well. We only add these aliases if they do not exist (like a polyfill). -
inspect
andtoString
should be added/overriden and provide the formatTypeName value
, providingFunction
if a function is the underlying value. (may wanna bring in theinspect
from crocks)
That should be enough to get started. One thing to note, it is very important that we do not change the original definition, so we may need to create a dependency on daggy and return a new definition (but this could lead to version 🌽flicts, so I am curious what you come up with).
Also I started a repo (unless you wanted to own one), I will throw in a build system and specs and CI and all the goodies soon. crocks-daggy
Had a while to think about this further and put crocks into more use, and I've come to realise that I was a bit wrong in my initial description of the problem (mostly due to a misunderstanding on my own part).
The missing element is actually pattern-matching API for crocks' types. I can use .either
with a Maybe, Result, etc., but I can't use a more verbose notation where I actually pattern match on the type (like union-type
's case
).
This is both a pro and a con:
- Pro: I can use whatever union type library I want, and there won't be any confusion about the pattern matching APIs with the crocks' types.
- Con: obviously I cannot pattern match on crocks' types. This is useful for onboarding, making the code more verbose and easier to read.
Bottom line, the current situation allows me to mix & match crocks
with any union type library without worrying about confusion APIs.
For interoperability of custom union types and crocks it would be helpful to have documentation that details the methods a type would require to be able to work with the different functions provided in crocks. For example, having to implement an either
method to be able to use the either
pointfree, or an ap
for others, etc.
Just to chime in on this, the pattern matching @leeor describes in their last comment makes a lot of sense to me (I've gone to use this sort of thing quite a few times and had to find alternate ways of working).
I'd also second a crocks-daggy package where we can create union types that interop with crocks by default. I love daggy because you can easily create taggedSums or single instances (without ending up in Person.Person()
land like union-type). However, I'd love to see the _
wildcard pattern from union-type in a daggy like package as that saves an awful lot of needless repetition!
So, I guess, +1 - I'd love to help out if anything gets going
I just want to second this request, some sister library or extension to define sum types and support for (de)serialization would be great. Not 100% sure on the dependency on Daggy. Although Daggy is great and I use it in almost all my projects, I am more of a fun of shallow dependency tree when it come to a choice. Also I would like to help out if needed.
I was thinking, if we want union types.
@karthikiyengar just added a n-Tuple type for simple Products, how would you all feel about a Union
type that will provide something along the lines of a tagged-sum in daggy. But with a more crocks-y feel and API.