11 ms·
I think I've solved the Haskell records problem
- slashnull 12y agoString typing to the rescue!
- eru 12y agoIsn't this closer to `string-kinding'?
- slashnull 12y agoMhyes, it appears that I misunderstood the precise mechanism of this lib. I don't know how to feel about the use of template Haskell in this lib (beyond the fact that it seems like it works great and avoids the curse of the weird error messages). I'm tempted to see it as a proof that, while deconstructive pattern matching is great (I really mean it!), it's nearly impossible to get rid of antediluvian dot accessor syntax/semantics. Either way I'm too tired and incompetent with Haskell to have a meaningful opinion on that.
- stingraycharles 12y agoFor the uninitiated, this solves a major (major!!) pain in the Haskell community: the lack of namespacing. If you declare two records with an 'id' field in the same module, you would get conflicts. People have been either using prefixing (fooId and barId) or splitting up modules to solve this problem, which can both considered to be ugly hacks. I am so glad the author has been able to pull this off, and it is one of those "why didnt anybody think of this before, it is so obvious!" moments.
- agumonkey 12y agoIt feels unnatural to see any new feature in the Haskell world that is neither from nor in the form of a PhD paper.
- eru 12y agoSimon Peyton Jones doesn't have a PhD, and he's the main force behind ghc.
- agumonkey 12y agoHa, wrong assumption(sic) on my side. He's been part of the research side of things for so long. To my defense his publications are in the form of research papers.
- nkhodyunya 12y agoHe actually got his PhD in December, 2013.
- danieldk 12y agoVan Laarhoven lenses were also introduced in a blog post :): http://www.twanvl.nl/blog/haskell/cps-functional-references http://www.twanvl.nl/blog/haskell/cps-functional-references
- m_mueller 12y agoCould you expand on what's the scope of the 'record' intrinsic? Is it used for as many things as Python's `dict`? I sure hope not, otherwise I'm wondering how anyone could have gotten much done in this language before.
- stingraycharles 12y agoIt's more like a struct from C.
- ARussell 12y agoIt's essentially Haskell's version of a class, except Haskell isn't object-oriented. It holds data. So yes, you could view it as a dict, of sorts. Except each key in this dict/record generates a top-level function.
- m_mueller 12y agoHow did having no namespaces in these things not become a massive headache for everyone? That would be the absolute killer argument for me to immediately switch to a different language if somehow possible.
- bodhi 12y ago> you cannot have two records share a field name in a single module (emphasis added.) I'm still a Haskell beginner, so I'm not the best person to comment on how this works out in practice.
- stingraycharles 12y agoSo far it's more an inconvience -- in practice it doesn't surface that often, since modules represent the namespaces in Haskell. If you run into naming conflicts very often, chances are your modules are not isolated enough. You don't use records as often as you use classes in an OOP language, for example. Having said that, a lot of projects seem to have a general Types.hs where they declare all the types they share between modules. This is a great solution for that.
- mietek 12y ago> Lack of namespacing … in the same module To clarify: 1. You can’t have more than one function with the same name in the same module. 2. Standard record accessors are functions.
- yummyfajitas 12y agoIt seems to me that most of these issues could be solved at the syntactic level simply by allowing recordval.fieldname syntax. I truly don't understand why Haskell doesn't allow this - anyone have some insight?
- joelwilliamson 12y agorecordval.fieldname would have the same syntax as function composition func1.func2 Since you should know the type of the first argument to '.', it is possible to disambiguate, but it would be a pretty significant corner case in the grammar.
- wcbeard10 12y agoThat was my intuition as well, but doesn't seem to explain why we can still use the syntax with modules (i.e., Set.map), unless the capitalized module name makes all the difference.
- jozefg 12y agoIt does, it's ambiguous to have `Constructor.fun` for this reason.
- deleted 12y ago[deleted]
- yummyfajitas 12y agoOne could simply choose an alternate symbol, e.g. record~>fieldname (which is similar to C++). I admit choosing a symbol in Haskell is a bit harder, since most of the easy ones are already taken.
- chongli 12y agoYes and Haskell allows arbitrary user-defined operators. Once the genie is out of that bottle it's hard to put it back inside!
- 12y ago
- pekk 12y agoI think I have a radical idea: use a language which solves this problem by design from the beginning. Much simpler.
- cbd1984 12y ago> use a language which solves this problem by design from the beginning Now you either give up everything else Haskell gives you, or you've created a new language. Do you see how both of those solutions are problems in and of themselves?
- nikita-volkov 12y agoThere is a problem. I know no other language, which manages to have at the same a type system as powerful, abstractions as insightful, as good a support for concurrency and parallel programming, an ecosystem as rich and which performs as well. Usable records are just an icing on the cake, but it's the cake that matters.
- eru 12y agoAnother way to solve this problem, is to allow multiple (nested) modules per file. A bit like OCaml. Then standard Haskell-syntax can already handle everything we need.
- eru 12y agoAnd I thought lenses were the canonical solution by now? EDIT: Reading the article a second time enlightened me.
- conistonwater 12y agoIsn't this solved (or addressed) by OverloadedRecordFields in GHC 7.10? https://ghc.haskell.org/trac/ghc/wiki/Records/OverloadedRecordFields https://ghc.haskell.org/trac/ghc/wiki/Records/OverloadedReco... https://ghc.haskell.org/trac/ghc/wiki/Records/OverloadedRecordFields/Design https://ghc.haskell.org/trac/ghc/wiki/Records/OverloadedReco...
- tmhedberg 12y agoSadly, OverloadedRecordFields won't be making it into 7.10.
- mijoharas 12y agoThat's a shame, do we know why? is it just not finished being implemented? I found a page[0] that said at some point they had stalled on refactoring something. [0] https://ghc.haskell.org/trac/ghc/wiki/Records/OverloadedRecordFields/Implementation#Currentstatus https://ghc.haskell.org/trac/ghc/wiki/Records/OverloadedReco...
- tmhedberg 12y agoThere's some info here: http://www.reddit.com/r/haskell/comments/2pnjdk/is_overloadedrecordfields_getting_it_into_7101/ http://www.reddit.com/r/haskell/comments/2pnjdk/is_overloade.... tl;dr: The patch worked but was messy/overly complex, so it needs refactoring before it's merged.
- millstone 12y agoWhat's a "quasi-quoter?"
- dons 12y agoSyntax macros.
- a-saleh 12y agoIt is a way to create embedded DSLs in haskell. If I understand correctly, when haskell compiler sees [foo|some dsl language inside|] it knows, that it should use parser asigned to foo on string inside of quasi-quotes. Long time ago, I tried learning this using this tutorial http://quasimal.com/posts/2012-05-25-quasitext-and-quasiquoting.html http://quasimal.com/posts/2012-05-25-quasitext-and-quasiquot...
- chriswarbo 12y agoA quoted value is exactly what is written, for example in LISP: (let ((foo "hello")) (quote (My name is foo))) > (My name is foo) An unquoted value is interpreted completely: (let ((foo "hello")) (My name is foo)) > Error: "My" is not a function A quasiquoted value is literal by default (like a quoted value), but we can selectively "unquote" parts, to have them interpreted: (let ((foo "hello")) (quasiquote (My name is (unquote foo)))) > (My name is "hello") As you can see, in LISP we can use quasiquotes on pretty much anything. Most other languages with quasiquotes only support it in strings; for example in PHP ' is the quotation mark and " is the quasiquotation mark: $foo = "hello"; echo 'My name is $foo'; // Gives 'My name is $foo' echo "My name is $foo"; // Gives "My name is hello"; Depending on the language, some require explicit unquoting (eg. ${} syntax), others require explicit escaping (eg. \$ syntax). The article uses two forms of quasiquotation marks: [r| and |], and [l| and |] For example: person :: Person person = [r| {name = "Yuri Alekseyevich Gagarin", birthday = {year = 1934, month = 3, day = 9}, country = {name = "Soviet Union", language = "Russian"}} |] Here the value of "person" is quasiquoted, so some parts of its contents (eg. the "{", "}", "," and "=" syntax, along with the "name, "birthday", "year", "month", "day", "country" and "language" tokens) will take their 'literal' values in the record-building language. The other values, '"Yuri Alekseyevich Gagarin"', "1934", "3", "9", '"Soviet Union"' and '"Russian"' will be interpreted as Haskell values, and the results (various Strings and Nums) will be used in the record-building language, instead of their literal tokens.
- ximeng 12y agoNice article. Could anyone comment on this: "Haskell syntax parsing needs to be reimplemented in the “record” library" That sounds like a big, unending task. How hard would it be for this to be implemented as an actual Haskell feature, without quasi-quoting etc.?
- tel 12y agoIt'd be a consensus thing more than anything else. I for one am not sure that this is a sufficiently correct feature to implement in language. But that said, Haskell's LANGUAGE extension system does allow things like this to be easily added to the language in a smooth way.
- ximeng 12y agoIt does look like a pretty clean implementation, I find myself wondering what the downsides are given all the positive comments in the article.