I am interested in how the Haskell runtime manage memory and how does it take advantage from laziness and purity.
Can you provide me with relevant links [and maybe explanations] please ?submitted by nawfel_bgh
[link] [6 comments]
I've recently started porting my code from gloss to free-game. While I'm generally happy with some things (the amount of documentation, screen vs cartesian coordinates and richer text handling), I've been struggling with the library other's choice of typeclasses to represent a lot of abstractions instead of ADTs and functions.
In particular, the Affine typeclass. Where I'd have expected things like circle, polygon, etc to be constructor functions that produced types, they are typeclass methods which (I think) produce types.
As a solid example, I wanted to create a rectangle function. I'd have expected to write something like:
-- pretending Picture2D is an ADT rectangle :: Double -> Double -> Picture2D
But instead, had to write rectangle :: (Picture 2D p) => Double -> Double -> p ()
What does the author of this library gain by using typeclasses so liberally? I'm sure that, as a novice, I'm missing some obvious points here.submitted by emarshall85
[link] [8 comments]
Following discussions with fellow haskellers, regarding the need to be careful with adding packages that could depends on GPL or proprietary licenses, it turns out it’s not easy to get your dependencies’s licenses listed.
It would be convenient to be able to ask the hackage database those things, and this is exactly what cabal-db usually works with.
The license subcommand is mainly to get a summary of the licenses of a packages and its dependencies, but it can also display the tree of licenses. Once a package has been listed, it would not appears again in the tree even if another package depend on it.
A simple example is better than many words:$ cabal-db license -s -t BNFC BNFC: GPL process: BSD3 unix: BSD3 time: BSD3 old-locale: BSD3 base: BSD3 deepseq: BSD3 array: BSD3 bytestring: BSD3 filepath: BSD3 directory: BSD3 pretty: BSD3 mtl: BSD3 transformers: BSD3 containers: BSD3 == license summary == BSD3: 14 GPL: 1
cabal-db is only using the license listed in the license field in cabal files, so if the field is incorrectly set, cabal-db would have no idea.
You may have seen this lecture by Yaron Minsky for some Harvard undergraduates. The title of the lecture is Effective ML, but many of these principles apply to Haskell as well. There is a part of the lecture around 18:05 where he talks a bit about
- Make illegal states unrepresentable
I guess this got me thinking. Making illegal states unrepresentable is something I'm familiar with and the example he gives is pretty simple.
But what about making illegal state transitions unrepresentable? I've only had a year of self-taught experience with Haskell/FP so I'm wondering what are (hopefully practical) strategies that I can use to manage this?
This is probably a pretty vague question, so I'm hoping also to start a conversation to help me clarify it.submitted by chebertapps
[link] [31 comments]
There are some really useful Haskell libs that solve some problems that you wouldn't even know if you weren't told beforehand. For example, there is a library that allows you to write a list-operating function once and automatically get its inverse. It could cut the work in half of things like creating an editor for a view of some data.
This led me to wonder, how many neat libraries are around there that every programmer should know before starting a new project?submitted by SrPeixinho
[link] [79 comments]
I recently asked this SO question:
The answer made me realize that the many times I've heard "do-notation is just syntax sugar used to replace >> and >>=" isn't as straight forward as I would have thought. I now know that do-notation and the Monad fail function are related.
I now see do-notation as indispensable instead of a mere syntax-sugar-convenience. I know it's technically just syntax sugar, but desugaring do-notation with certain Monads seems difficult. If there is a generally applicable way of desugaring do-notation I would like to know about it. So far I've only seen naive approaches to desugaring which ignore the error handling behavior of do-notation.
I've gathered this is a controversial design, and I don't want to restart a debate that has surely happened before. But I do want to ask:
Is Monad fail really necessary? It seems to me that by removing Monad fail and changing the bind (>>=) implementation you could get the same "error handling" behavior from the Monad while simplifying how do-notation works. Could this be done?submitted by Buttons840
[link] [12 comments]
It’s been exciting to see the positive reception in the tech press and the open source community to Hack, the new programming language that my team at Facebook released last week.
At the same time, one part of that coverage has made me wince: a couple of articles give the impression that I created Hack, but I didn’t. What I do is manage the Hack team, and since I’m incredibly proud of the work they do, I’d like to shine a little light on the people who really deserve the credit.
A few years ago, Julien Verlaguet and Alok Menghrajani had a notion that Facebook could improve some aspects of how it ships software. They developed a proof-of-concept of a system that could detect certain kinds of logic error in a program, and showed it to a few colleagues. Buoyed by the positive feedback they received, they decided to invest more effort in the project, which would in due course become Hack.
This process underscores one of the aspects I find most appealing about engineering at Facebook: engineers are welcome to try out bold ideas, and to push on with them if they look like they’ve got a good prospect of paying off.
The work that Julien and Alok did to get the project off the ground was far from simple. They had to design not just a type system, but one where the type checking algorithms could scale to run efficiently and incrementally across hundreds of thousands of source files. Not just a static type system, but one that could interoperate seamlessly with PHP’s dynamic types. Even the notionally simple act of watching the filesystem to quickly find changed files is impressively difficult; just ask anyone who’s had to wrestle with race conditions involving Linux’s inotify subsystem.
When presented with the early prototype of Hack, Drew Paroski went beyond simply offering support: he immediately signed up to enrich Hack by building the Collections system, a set of clean, modern APIs for dealing with bulk data. While the face that Collections presents to the programmer is easy to understand, there’s once again a lot of subtle work going on behind the scenes (including a lot of runtime support in HHVM, to make them efficient). Collections interoperate seamlessly with PHP arrays, both when a program is being typechecked and while it’s running.
While designing a language and building a typechecker are substantial efforts in their own right, a big reason that we’re excited about Hack is that it is already a success within Facebook. This is in large part due to the work of two engineers, Gabe Levi and Josh Watzman, who converted a large part of our codebase to use Hack’s type annotations. Pulling this off is a surprisingly subtle task. In a large dynamically typed codebase, there can be both latent type errors and code that is more elegantly left dynamically typed. Introducing static types on a large scale involves a series of judgment calls: is what we’re looking at an error; a piece of code that we can refactor so that we can express its types statically; or something that’s just fine as it stands?
As the rest of the team proceeded with the language design, engineering, and conversion work, Joel Marcey built out the HHVM and Hack documentation, while Eugene Letuchy both added features to the language (e.g. richer support for traits) and made significant contributions to our PHP-to-Hack conversion work.
I’m proud to be associated with such skilled people who put so much passion and care into their work. When it comes to Hack, I’m simply the messenger, and these engineers have all along been the ones making it happen.
With 19 new releases, postgresql-simple has seen substantial development since my announcement of version 0.3.1 nearly a year ago. Compared to my last update, the changes are almost exclusively bugfixes and new features. Little code should break as a result of these changes, and most if not all of the code that does break should fail at compile time.
As it stands today, postgresql-simple certainly has the best support for postgres-specific functionality of anything on hackage. So, for a few highlights:Parametrized Identifiers
Thanks to contributions from Tobias Florek, perhaps the most exciting change for many is that postgresql-simple now properly supports parametrized identifiers, including column, table, and type names. These are properly escaped via libpq. So for example, you can now write:execute conn "DROP TABLE IF EXISTS ? CASCADE" (Only ("schema.table" :: QualifiedIdentifier))
Of course, this particular example is still potentially very insecure, but it shouldn’t be possible to create a SQL injection vulnerability this way.
The downside of this change is that postgresql-simple now requires libpq version 9.0 or later. However, community support for 8.4 is coming to and end this July. Also, it is possible to use newer versions of libpq to connect to older versions of postgres, so you don’t have to upgrade your server. (In fact, in one particular situation I’m still using postgresql-simple to connect to postgresql 8.1, although some features such as non-builtin types don’t work.)Copy In and Copy Out support
While the postgresql-libpq binding has supported COPY FROM STDIN and COPY TO STDOUT for some time, postgresql-simple now supports these directly without having to muck around with postgresql-libpq calls via the Internal module.
If you are interested in streaming data to and from postgres, you may also be interested in higher-level COPY bindings for pipes and io-streams. This is available in Oliver Charles’s pipes-postgresql-simple, which also supports cursors, and my own unreleased postgresql-simple-streams, which also supports cursors and large objects.Out-of-box support for JSON, UUID, and Scientific
Thanks to contributions from Joey Adams, postgresql-simple now has higher-level support for savepoints in the Transaction module, as well as the ability to nest the fold operator. Previously, postgresql-simple had assigned a static name to the cursor that underlies fold, and now every connection has a counter used to generate temporary names.Parametrized VALUES expressions
For example, these situations commonly arise when dealing with writable common table expressions. Let’s say we have a table of things with an associated table of attributes:CREATE TABLE things ( id SERIAL NOT NULL, name TEXT NOT NULL, PRIMARY KEY (id) ); CREATE TABLE attributes ( id INT NOT NULL REFERENCES things, key TEXT NOT NULL, value BIGINT NOT NULL );
Then we can populate both a thing and its attributes with a single query, returning the id generated by the database:query conn [sql| WITH thing AS ( INSERT INTO things (name) VALUES (?) RETURNING id ), newattrs AS ( INSERT INTO attributes SELECT thing.id, a.* FROM thing JOIN ? a ) SELECT id FROM thing; |] ("bob", Values [ "text" ,"int8" ] [ ( "foo" , 42 ) , ( "bar" , 60 ) ])
The empty case is also dealt with correctly; see the documentation for details.Improved support for outer joins
A long standing challenge with postgresql-simple is dealing with outer joins in a sane way. For example, with the schema above, let’s say we want to fetch all the things along with their attributes, whether or not any given thing has any attributes at all. Previously, we could write:getAllTheThings :: Connection -> IO [(Text, Maybe Text, Maybe Int64)] getAllTheThings conn = do query conn [sql| SELECT name, key, value FROM things LEFT OUTER JOIN attributes ON things.id = attributes.id |]
Now, the columns from the attributes table are not nullable, so normally we could avoid the Maybe constructors, however the outer join changes that. Since both of these columns are not nullable, they are always both null or both not null, which is an invariant not captured by the type. And a separate Maybe for each column gets awkward to deal with, especially when more columns are involved.
What we would really like to do is change the type signature to:getAllTheThings :: Connection -> IO [Only Text :. Maybe (Text, Int64)]
And now we can, and it will just work! Well, almost. The caveat is that there is a separate instance FromRow (Maybe ...) for most of the provided FromRow instances. This won’t work with your own FromRow instances unless you also declare a second instance. What’s really desired is a generic instance:instance FromRow a => FromRow (Maybe a)
This instance would return Nothing if all the columns that would normally be consumed are null, and attempt a full conversion otherwise. This would reduce code bloat and repetition, and improve polymorphism and compositionality.
But alas, it’s not possible to define such an instance without changing the FromRow interface, and quite probably breaking everybody’s FromRow instances. Which I’m totally willing to do, once somebody comes up with a way to do it.