Typeclasses #24

Closed
wants to merge 32 commits into
from

Projects

None yet

5 participants

@gmpl
gmpl commented Dec 22, 2011

Existing code was refactored in order to define Typeclasses in a more generic way.

gmpl added some commits Dec 14, 2011
@gmpl gmpl + Functor 057bf55
@gmpl gmpl + Monad 4e89a22
@gmpl gmpl + Applicative Functor. 2381a1d
@gmpl gmpl - Instances for Seq: Overloads with Interfaces don't play well with T…
…ype Inference. It could be implemented later with a wrapper.

- Instances for IEnumerator: Was a dummy instance to help Type Inference with seq.
6b29d73
@gmpl gmpl + Monoid e3fda5c
@gmpl gmpl + Do notation builder. 0b398d1
@gmpl gmpl Rename deprecated Monoid Type. 8a9544c
@gmpl gmpl Rename deprecated State Type. 7ad69f5
@gmpl gmpl Rename deprecated Reader Type. 6b2110b
@gmpl gmpl Rename deprecated Writer Type. 92f1ee6
@gmpl gmpl + State 4f7b784
@gmpl gmpl Renamed existing Builders that will be replaced. c560c67
@gmpl gmpl Rename deprecated Cont Type. c2de5f5
@gmpl gmpl + StateBuilder 4d3346f
@gmpl gmpl + Reader
+ ReaderBuilder
+ Some type annotations, fixes
d0d1c13
@gmpl gmpl + Writer
+ WriterBuilder
e69bbbd
@gmpl gmpl Writer Test fixed. 7c9d51c
@gmpl gmpl + More generic functions and operators for Monad and Applicative Func…
…tor.
58a86e8
@gmpl gmpl + Writer instances for Applicative Functor. bb7dca1
@gmpl gmpl + Choice instances for Functor, Applicative Functor and Monad.
Some comments removed.
7bb935a
@gmpl gmpl Non-generic code removed from Choice Module. eea46dd
@gmpl gmpl Choice and Validation adapted. e24bb2d
@gmpl gmpl ReaderTests adapted.
Old code from Monoid and Reader removed.
c29c008
@gmpl gmpl Async module adapted. 0680578
@gmpl gmpl ZipList module adapted. 0e49882
@gmpl gmpl Option module adapted. 70057a1
@gmpl gmpl Nullable module adapted. 146fb3b
@gmpl gmpl State and Undo Adapted. f9ee489
@gmpl gmpl Cont adapted. e366b12
@gmpl gmpl Distribution adapted. 431347b
@gmpl gmpl + Applicative functor to all monads.
+ Type annotations to guide type inference to the right signature.
1546f26
@gmpl gmpl - Operators Module. 00ef72d
@panesofglass

What about async?

Owner
gmpl replied Dec 24, 2011
@panesofglass
Contributor

This looks good to me.

@forki
Member
forki commented Jan 4, 2012

what's the status on this?

@mausch
Member
mausch commented Jan 4, 2012

@forki see discussion above. This needs more use to uncover all problems so we can make an informed decision about making this part of master.

@ghost
ghost commented Mar 8, 2012

Have there been any news on this subject?

@mausch
Member
mausch commented Mar 8, 2012

@ohwow status is still the same. Any input would be appreciated (in the mailing list).

@mausch
Member
mausch commented May 8, 2012

Just as an update: I have been working a little on this in my fork: https://github.com/mausch/fsharpx/tree/typeclasses, and found a number of cases where type inference breaks or seemingly correct code won't typecheck.
As usual, help is always welcome.
Also, I talked to Gustavo a while ago, he mentioned he was working on an alternative that had better type inference, so watch http://code.google.com/p/fsharp-typeclasses/ .

@gmpl
gmpl commented Jun 13, 2012

Hi

As Mauricio said, I'm working in an alternative solution.

http://code.google.com/p/fsharp-typeclasses/#Alternative_Solution
I just uploaded this alternative version of the approach, without
operators, which will make it more flexible as we can specify explicitely
the constraint when calling the static method.

It requires to fix a bug in the F# Parser, but it's included, so you can
recompile F# and experiment with it (that's what I will be doing from now
on).

Regards

Gustavo

On 8 May 2012 17:37, Mauricio Scheffer <
reply@reply.github.com

wrote:

Just as an update: I have been working a little on this in my fork:
https://github.com/mausch/fsharpx/tree/typeclasses, and found a number of
cases where type inference breaks or seemingly correct code won't typecheck.
As usual, help is always welcome.
Also, I talked to Gustavo a while ago, he mentioned he was working on an
alternative that had better type inference, so watch
http://code.google.com/p/fsharp-typeclasses/ .


Reply to this email directly or view it on GitHub:
#24 (comment)

@gmpl
gmpl commented Aug 30, 2012

Q: Why did you choose Choice1of2 as the "Right Choice"? Is there any special reason?
The problem I see is we have here the Right parameter at the Left side, ie: Choice<'right,'wrong>.
In any case we can't partially apply the type to express it as a Monad (Functor or Applicative) because at the moment we don't have higher order kinds in F#, but still breaks the convention and the mnemonic ("right" also means "correct") and I think it can be tricky for a person coming from Haskell or other languages like Scala.
Even if it is not used as a "Value or Error" the idea is to fix the first parameter and play with the second.

@mausch
Member
mausch commented Aug 30, 2012

Async.Catch uses that convention, so we went with that.
Personally, my mnemonic is "first assume things go well", therefore Choice1Of2 carries the "Right" value.
You can still partially apply the type arguments at the datatype level, e.g.

data AEither a b = ARight a | ALeft b
data AMaybe a = AEither a ()

For instances, I think you can use a Flip type combinator, though I'm not sure and it would still be kinda annoying.

@gmpl
gmpl commented Aug 30, 2012

OK, I guess that's a good reason. My next question is about Nullable.
Since we can't create an Applicative Functor for Nullable it makes no sense to define a Nullable Monad.
Having Nullable as a monad would lead to compilation errors when using generic functions, not just ap.
As Functor is probably fine, as long as you don't try to map to a reference type, ie fmap string (Nullable 5)

@mausch
Member
mausch commented Aug 30, 2012

Good point, I didn't realize that Nullable isn't really a monad. I don't think it's even a functor.
Still, Nullable.bind, Nullable.map, Nullable.lift2 etc seem useful, maybe we could just rename them or otherwise make it very explicit in the comments that they're not functorial, monadic, etc.

@gmpl
gmpl commented Aug 30, 2012

I think is a Restricted Monad, like Ord a => Set a (F# notation: Set<'a>
when 'a : comparison).
There you have the same problem, since a function is not an instance of Ord
there is no Applicative instance.
But AFAIK they obey all Functor laws, if you consider the Category
restricted to those restricted types.

In Haskell it's a problem to code Restricted Monads, you need an extension,
but in F# using this technique is fine as long as you know what you're
doing.

For now,as you said, we can just add a comment making it very explicit that
it's a Restricted Monad.

Gustavo

On 30 August 2012 20:19, Mauricio Scheffer notifications@github.com wrote:

Good point, I didn't realize that Nullable isn't really a monad. I don't
think it's even a functor.
Still, Nullable.bind, Nullable.map, Nullable.lift2 etc seem useful, maybe
we could just rename them or otherwise make it very explicit in the
comments that they're not functorial, monadic, etc.


Reply to this email directly or view it on GitHubhttps://github.com/fsharp/fsharpx/pull/24#issuecomment-8169109.

@panesofglass
Contributor

What's the status on this?

@gmpl
gmpl commented Feb 26, 2013

Since I did this pull request, this approach was refined and finally I decided to create a new Project: FsControl.

The goal is to get the same functionality but in a less intrusive way, I mean not forcing everybody to a specific name convention or style (Haskell vs F#).

At the same time there were some discussions about splitting FSharpx in separated DLLs.
Also there were people complaining about methods published in FSharpx , wanting to move them to a specific module.
This new project is aligned with those discussions.

It contains just the basic overloads but does not define generic functions, so if used in FSharpx or other project it's the project which should create the generic functions.
It also allows the project to add overloads for his types, so even if you don't want to use or define generic functions in your project you can add overloads to your types, someone else might be interested to use your types in generic functions.

FsControl is basically an overload repository, there might be projects that add overloads to it, projects that use the overloads for generic functions and projects that do both.
Mauricio did an example which shows how to use FsControl.

For F#x I propose to link this dll, add overloads for all Monads, Applicatives, etc and eventually define some generic functions inside a module for people wanting to use this approach.
I can do a branch to show how it will look like.

@jackfoxy
Contributor

Whether in FSharpx or the new FsControl project, please write XML comments (documentation) on all types and functions, and write a comprehensive readme.md. Otherwise this excellent work is only accessible to the most motivated individuals. The way to spread adoption of F# is to make work like this more accessible.

@mausch
Member
mausch commented Feb 26, 2013

Also worth noting is that this has to be within FSharpx, i.e. if we want fmap for RoseTree, the Functor instance has to be defined either along with the definition of the Functor "typeclass" or when defining the RoseTree type.
Otherwise you run into the same problem as with orphan instances in Haskell.
So either FSharpx takes a dependency on FsControl, or it includes/merges FsControl, but the instances for the typeclasses can't be defined in a third assembly.
Technically speaking, another possibility would be having FsControl depend on FSharpx, but that doesn't seem like a good idea, it would be like having the Functor class depend on particular instances of it.
Gustavo, please correct me if I'm wrong :)

As the Haskell wiki says in http://www.haskell.org/haskellwiki/Orphan_instance : "If you encounter a missing instance for a class or a type of a package, resist to define your own orphan instance, because it will likely collide with such instances of other packages, or it will collide with new instances added in later versions of that package. Instead ask the package author to add your instance."

I'd just take the dependency on FsControl. Since FsControl doesn't export any operators or even functions, we can later decide whether we want to add a new module with the overloaded functions/operators binding to typeclasses or not, but that would be a separate discussion.

Also, this wouldn't have any impact on current client code of FSharpx. Users would be able to choose between the typeclassy way of doing things, or the traditional, more fsharpish style. Both have pros and cons.

@ghost
ghost commented Jun 24, 2013

Can we close/archive this request? It is very old.

@forki forki closed this Jun 24, 2013
@gmpl gmpl referenced this pull request in gmpl/FsControl Oct 31, 2015
Closed

The description requires a rewrite or clarification #49

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment