[Excitement]
Not only do I now know what a functor is (from a category theory standpoint) and roughly how they relate to Haskell type classes, but I ALSO know how to emulate a functor in F# with SRTPs!!!! What does this mean in practice? It means that I can implement a new data structure with different performance characteristics, like a FastList<T> as well as a RegularList<T>, and yet I can just use one map function for both kinds of lists as well as any other list-like data structures I implement.
What this means in effect: I can now do overloading in F#!
My code is about to shrink significantly! And I will be able to add new data structures fairly freely. My code no longer grows in complexity if I add more data structures. (!!!!!!)
Here's the relevant commit: https://github.com/MaxWilson/ShiningSword/commit/1d4cdbac77983ed808f96489083ccc9ecae0377a
Notice how FastList is now a type, not a module, so I just declare FastList<T> instead of FastList.Data<T>, and instead of having to call FastList.Transform I can just call transform.
Limitations: you need to have enough control over the source code to add the appropriate static members for SRTP to operate against, which in some cases for e.g. built-in lists might require wrapping native types in my own types. And all the types involved need to have roughly the same type signature, so you have to follow certain design patters when adding your new types. But as long as you do that, everything just works.
Thanks to Bartosz Milewski and his book (Category Theory For Programmers) and also to Don Syme and his paper on the history of F#, or I would never have thought to attempt this or understood the results even if I succeeded.
-Max
--
I could not love thee dear, so much,
Loved I not honor more.
Not only do I now know what a functor is (from a category theory standpoint) and roughly how they relate to Haskell type classes, but I ALSO know how to emulate a functor in F# with SRTPs!!!! What does this mean in practice? It means that I can implement a new data structure with different performance characteristics, like a FastList<T> as well as a RegularList<T>, and yet I can just use one map function for both kinds of lists as well as any other list-like data structures I implement.
What this means in effect: I can now do overloading in F#!
My code is about to shrink significantly! And I will be able to add new data structures fairly freely. My code no longer grows in complexity if I add more data structures. (!!!!!!)
Here's the relevant commit: https://github.com/MaxWilson/ShiningSword/commit/1d4cdbac77983ed808f96489083ccc9ecae0377a
Notice how FastList is now a type, not a module, so I just declare FastList<T> instead of FastList.Data<T>, and instead of having to call FastList.Transform I can just call transform.
Limitations: you need to have enough control over the source code to add the appropriate static members for SRTP to operate against, which in some cases for e.g. built-in lists might require wrapping native types in my own types. And all the types involved need to have roughly the same type signature, so you have to follow certain design patters when adding your new types. But as long as you do that, everything just works.
Thanks to Bartosz Milewski and his book (Category Theory For Programmers) and also to Don Syme and his paper on the history of F#, or I would never have thought to attempt this or understood the results even if I succeeded.
-Max
--
I could not love thee dear, so much,
Loved I not honor more.
No comments:
Post a Comment