6 ms·
What I wish to see in these blog posts are real-world examples. My day job is coding an MVC app in Rails / Ember. Fine, I won't be able to get past Chapter 11 i
by chowes 10y ago
What I wish to see in these blog posts are real-world examples. My day job is coding an MVC app in Rails / Ember. Fine, I won't be able to get past Chapter 11 in a book, but what am I REALLY missing out on? Are these solutions meant for a different problem set, or would I be able to use these concepts in my day-to-day (assuming we were written in a Scala, Haskell, etc.)?
- deleted 10y ago[deleted]
- daxfohl 10y agohttp://stackoverflow.com/questions/21170493/when-are-higher-kinded-types-useful/21174565 http://stackoverflow.com/questions/21170493/when-are-higher-... Also, my practical-oriented blog posts on the topic in .net (referenced in my own answer on that page): http://www.sparxeng.com/blog/software/an-example-of-what-higher-kinded-types-could-make-possible-in-c http://www.sparxeng.com/blog/software/an-example-of-what-hig... http://www.sparxeng.com/blog/software/higher-kinded-fun-in-haskell http://www.sparxeng.com/blog/software/higher-kinded-fun-in-h...
- chowes 10y agoThat first blog post of yours was great, FYI - exactly what I was looking for.
- daxfohl 10y agoA simpler example would be say amplifying a signal functor. In Haskell, let amplify x f = fmap (x *) f amplify 2 [1,2,3] >> [2,4,6] cos pi >> 1.0 let doublecos = amplify 2 cos doublecos pi >> 2.0 You can't do anything that operates so generically in a language without HKTs. All that said, I don't find them all that useful in day-to-day work.
- willtim 10y agoFirst of all, a Ruby developer would need to be convinced of the value of static types, in his/her domain. For the maintenence of large complex systems, they are invaluable, for web development perhaps less so. Advanced type systems simply allow one to statically verify more invariants, or in the case of higher-kinded types, allow one to make more sophisticated abstractions and reduce boilerplate. It's important to remember that every statically typed language is capable of being dynamically typed also. I can use string-keyed dictionaries and runtime tagged types in Haskell if I ever need to. What you loose is ease-of-use, which I guess is why Ruby is more popular than Haskell.
- marcosdumay 10y ago> What you loose is ease-of-use After a while using Haskell, I'm not sure about that anymore. I keep thinking that an "easier than rails" web framework is just one breakthrough by some random developer somewhere on the Internet away. Even if I can't imagine the form such library would take, the features I see every day are so powerful that it just look possible.
- harveywi 10y agoAre you familiar with C# or Visual Basic? LINQ [1] is a tragic example of what happens when a host language does not support higher-kinded types - every time you use a LINQ method on a concrete type that may have important semantics, its (static) type gets downgraded to a plain "IEnumerable<X>". This can cause major bugs and headaches when trying (intentionally or inadvertently) to write code to abstract over various combinations of LINQ flavors such as "LINQ to Objects" and, say, "LINQ to Entities/SQL". The LINQ abstraction is leaky, half-baked, and not as safe as it should be. Some of the various "LINQ to X" flavors are actually unable to support certain operations (cf. [2]), so your software can unexpectedly fail at runtime. If C# and Visual Basic had support for higher-kinded types, then your LINQ-equipped thing wouldn't have to be punted back to an IEnumerable - it could retain its (static) type after applying LINQ methods. [1] https://msdn.microsoft.com/en-us/library/mt693024.aspx https://msdn.microsoft.com/en-us/library/mt693024.aspx [2] https://msdn.microsoft.com/en-us/library/bb738550(v=vs.110).aspx https://msdn.microsoft.com/en-us/library/bb738550(v=vs.110)....
- recursive 10y agoI assume by concrete type, you mean the actual run-time manifested type of an object. If that's true, you're slightly wrong. Most linq methods have parallel definitions for IQueryable<T>. (For those that don't, IQueryable<T> also extends IEnumerable<T>, so that's always a fallback.) In practice this means that not all linq methods return IEnumerable<T>. x.Where(...) may return a statically typed IEnumerable<T> or an IQueryable<T> depending on whether x was IQueryable<T>. Edit: I don't think linq would even actually improve by having this kind of fancy stuff. I don't want .Where() called on an array to return another array. I want a lazy IEnumerable<T> almost every time. I might want to consume only the first 10 elements from the filtered result. Allocating a whole 100000 array could be a tremendous waste of time.
- harveywi 10y agoThanks - you are right about the IQueryable/IEnumerable distinction - it's been a long time since I worked with C#. I think it is somewhat unfortunate that IQueryable is a subtype of IEnumerable because the semantics are so different and one can be so easily coerced into the other. For an alternative example of limitations induced by lack of higher-kinded type abstraction, imagine implementing an Option/Maybe type [1] in C# and piggybacking on LINQ. Under the LINQ API, if you try to do anything with an instance of your Option/Maybe, its static type gets obliterated into an IEnumerable, which destroys the semantics. (The fact that the thing is an Option/Maybe and not, say, a list of things, is important for reasoning about, building, and abstracting over things.) [1] https://en.wikipedia.org/wiki/Option_type https://en.wikipedia.org/wiki/Option_type
- dragonwriter 10y ago> My day job is coding an MVC app in Rails / Ember. Fine, I won't be able to get past Chapter 11 in a book, but what am I REALLY missing out on? Being focused on Ruby (or any dynamic language) makes the value harder to see, perhaps, since a lot of what HKT get you in a static language you don't need in a dynamic language -- its stuff you lose going from a dynamic language to a static language with an insufficiently powerful type system in exchange for typesafety. HKT let you have your cake and it eat it too (that is, lets you keep powerful abstractions that operate on classes of related types, while remaining typesafe.)
- chowes 10y agoKeeping your comment in mind while reading http://www.sparxeng.com/blog/software/an-example-of-what-higher-kinded-types-could-make-possible-in-c http://www.sparxeng.com/blog/software/an-example-of-what-hig... from below was super helpful. Thank you.
- talex5 10y agoHere's a common example. Some systems provide blocking operations: e.g. read_line waits for a line of text and then returns it as a string. Others use promises: read_line returns a promise of a string. What if you want to write a library that works with either blocking calls or asynchronous promises? The cohttp HTTP library is written that way. For example, the Transfer_io module[1] (supporting both chunking and non-chunking HTTP transfers) takes as an argument another module, IO[2], that provides a read_line function of type "ic -> string option t", where the type t is abstract and higher-kinded (and "ic" = input channel). You can instantiate the module with a blocking IO module (where a "string t" is just the same as a "string" and read_line blocks) or with a non-blocking one (where a "string t" is a promise for a "t" and read_line returns a promise). [1] https://github.com/mirage/ocaml-cohttp/blob/master/lib/transfer_io.mli https://github.com/mirage/ocaml-cohttp/blob/master/lib/trans... [2] https://github.com/mirage/ocaml-cohttp/blob/master/lib/s.mli https://github.com/mirage/ocaml-cohttp/blob/master/lib/s.mli (also useful if your language has multiple competing promise libraries...)
- pierrebai 10y agoYou don't need higher-kinded types for that. Just always return a promise, except the blocking version always return a promise that is already fulfilled. This is just a variation of 'any problem can be solved by adding a level of indirection' + 'any protocol can have a dummy implementation'.
- yummyfajitas 10y agoThe problem is that by doing this, you have made an operation that should be instantaneous - readLineFuture: () => Future[Line] - into something that now has built in lag. I.e. you've pulled the side effects (blocking) from the future to the present.
- IpV8 10y agoThat built in lag is so incredibly miniscule in the grand scheme of programming that 99.9999% of times it will not matter, and if it does you are using C or Assembly anyways.