Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Snap for Beginners: Haskell Web Development (snapforbeginners.com)
159 points by biscarch on March 1, 2014 | hide | past | favorite | 83 comments


Anybody know of solid super-entry level tutorials for starting Web Development with Haskell with less opinionated libraries like Scotty? Something that shows you how to slap together a solid cabal sandboxed ready-to-deploy application that's a mix of Scotty/Persistant/Esqueleto and all the other basics?

Clojure has "Web Development with Clojure" which is basically what I listed above, except for Clojure rather than Haskell.


I gave a talk at a Haskell meetup in London this week that covered some of this - the slides won't really be useful standalone, but I could probably re purpose them to a blog post fairly easily if you're interested?


Not sure about the OP, but I'd definitely love to read that.


Ditto


I know I would be very interested in this.


Please do, that sounds fantastic. Also, which meetup were you speaking at?



Would be pretty interested.


Sorry I missed the talk! Did it get videoed? They usually are.


Not this time I'm afraid. The format was 3 short talks so we didn't bother videoing.


Yes Please. Do you have a link to your blog?


I just figured out how to do this yesterday, here's the source of my barebones Scott/Persistent/Esqueleto app. All it does is insert some records into the db (sqlite), then runs a server that displays the first entry. (The entry is mixed into the scotty tutorial because I stopped as soon as I got something working). https://github.com/cgag/comments

I may write up a blogpost on getting this far. It's mostly based on this: https://www.fpcomplete.com/school/starting-with-haskell/libr... . I didn't do much beyond figure out explictly using L.fromStrict to deal with conflicting interpretations of overloaded-strings and figuring out how where to put my fillDB and getComments functions in main. I initially tried to call these within the scotty monad, but I think doing it that way would have required learning about monad transformers.

I'm hoping to eventually turn this into a simple disqus alternative that should be lightweight and easy to distribute as a binary.


There is this tutorial: http://adit.io/posts/2013-04-15-making-a-website-with-haskel...

Although it uses virthualenv instead of a cabal sandbox.


I read that article a few weeks ago in order to get a basic personal site server running on Heroku. I used a standard cabal setup and updated a few things.

end result here, which I think should serve as a good starter point for developing with Scotty:

https://github.com/chrissrogers/chrissrogers.com

For Heroku builds I used the following excellent buildpack

https://github.com/begriffs/heroku-buildpack-ghc


+1 thanks! Nice example. Scotty is appealing to me because it has a Sinatra like feel to it.


for a true beginner, it starts with an outdated cabal definition for virthualenv/hsenv that has specific old versions. nobody will be able to just copy and paste trhu the tutorial.

but it seems well written if you can get past that point. Most beginners won't though.


Post author here. I just updated the post to use cabal sandboxes.


At the lowest level, the Snap Framework is not at all opinionated. The base level of the framework is comprised of snap-core and snap-server. snap-core is a web server API roughly on the level of Yesod's wai with maybe a little more slightly higher-level functionality. snap-server is Snap's web server that implements the snap-core API--roughly equivalent to Yesod's warp.

I personally don't understand the draw of scotty because as soon as you want to start doing more substantial web development, you're going to want higher level abstractions. The Snap Framework adds to this in a pretty flexible and not-too-opinionated way with snaplets which are implemented in the snap package. The snap package also contains a few core snaplets that almost every application will want out of the box like sessions, auth, and a snaplet for Heist templating. The Heist part is the only place where the snap package gets opinionated. But you are definitely not locked into using Heist. You could very easily use Yesod's Hamlet, HStringTemplate, hastache, or anything else. Heist just happens to be the direction that the core Snap developers seem to prefer.


I am rading that book right now, is amazing. It makes Clojure so much easy, and the tutorials are well paced as explained.


I can't help you with the tutorials, but snap and happstack are no more opinionated than scotty. They just have documentation and a collection of useful libraries you can use with them.


Currently heading up a team of awesomely smart people building our back end in Haskell on snap. AMA!


How long do you think it'd take for a reasonably decent developer with no prior experience to pick up and become competent with Haskell and Snap?


I don't have a lot of data points, but for the one PHP developer I had learn haskell by writing a webapp in it, 6 months from "never seen haskell before" to "feels comfortable working solo and doesn't need help". The first 80% comes pretty quick, but not needing someone to answer questions takes a while.


This is helped by the fantastic haskell community. The IRC channels are great.


"the development SPEED of ruby with the SAFETY of STATIC TYPING" sounds kind of sketchy. Would you say that title is true?


What you find if you're doing it right is not only that you get the safety of static typing, but also that the types often lead you towards to solution.

Abstractions in Haskell are smaller, more universal and composable than those of say ruby or python. For example the very simple idea of a Monoid (essentially concatenation) can be found in most places either explicitly or if you squint a bit, and once you recognise it a whole set of properties and behaviours can be reused.

Also once the structure is in place, they types make for very safe re-factoring and assurance that you haven't broken anything.

The only thing that's probably slower than ruby in Haskell is, unfortunately, learning it in the first place :-)


As someone who is quite familiar with abstract algebra, but who has not used much Haskell, I'm curious about why you think of monoids as simply concatenation? Is this the only, or primary, way they are used in Haskell? A monoid could also be the natural numbers combined with addition for example. Would this not be as useful?


My take on why monoids seem to be thought of as concatenation in the Haskell community is that the other simple examples run into some difficulty with the way the type class system is set up. Specifically, the example you used requires a newtype wrapper, because the nats (ints really, we don't use nats much) are a monoid under both addition and multiplication. We don't have any better way of dealing with multiple instances, so we create a Sum newtype and a Product newtype. This adds enough friction that those instances seem to not get used all that much. Other examples of this are the Boolean monoid under conjunction or disjunction, and the monoid of endomorphisms under composition. Those instances all exist, but I rarely (if ever) see them used.

There are definitely some more general uses of the Monoid type class than concatenation that don't require newtypes, but they are slightly harder to understand, so they don't tend to get trotted out as examples. The best example I can think of is Ordering (LT | EQ | GT), which is a monoid in the sense of lexicographical ordering. You also have Function (a -> b) and Maybe b, which are each monoids when b is a monoid, but if b is a monoid under concatenation then those just look like concatenation too.

One other reason I think they're thought of as concatenation is that monoids under concatenation are extremely useful. The most common case is when appending things that are like strings. Strings are not performant, so for anything significant you want to use Text or ByteString. However, it's not uncommon to use Strings when you're first figuring things out. If you want to then switch over to Text and you used String appending (++), you'll have to find and replace every instance of that. If you instead used Monoid appending (<>), you can switch the types and everything will still work. Quite nice.


Haskellers just call them Monoid and happily include anything that's associative+identity. When talking to people not yet familiar with Haskell or abstract algebra, it's commonly a good idea to simplify the notion and call Monoid the same as concatenation. That's all.

    newtype Sum = Sum { getSum :: Int }
    instance Monoid Sum where
      mempty = Sum 0
      mappend (Sum a) (Sum b) = Sum (a + b)


I most definitely don't! :-)

I was trying to simplify to get a cross the point that the Haskell ecosystem contains small and very well factored abstractions, without busting out the mathjax and technical terms. I find the key understanding of Monoids (which lets me use them and gives me a useful intuition upon seeing one) to be "Oh this is just combining these things together" - which I explain to newcomers as "basically concatenation".

It's always hard to pick the correct amount of correctness to use :-)


Probably too late for you to see this, but free objects are very common in Haskell-land. And free monoids are basically concatenation. But you'll see all kind of monoids :)


Appending things is used as an example a lot of the time so people sort of get it into their heads that monoid = concatenation, which is obviously not true. I can't speak as to which monoids get used the most in Haskell but I have personally used it for appending string-like things, and also to unify data structures (combine the stuff in them basically). There is actually a library that will derive a Monoid instance for you if all of the types you're using are already instances.

http://hackage.haskell.org/package/generic-deriving-1.6.2/do...


yes, thats a commutative monoid. Thinking of a monoid as "concatenation" is much more general concept that includes that one


Only by removing all meaning from the word "concatenation" and taking is to mean "associative with identity" , which is what a monoid is. Concatenation is a special case, not the whole of monoid.


> A monoid could also be the natural numbers combined with addition for example.

Then you can think of it as concatenating two unary numbers.


Or multiplication.


n * m is the concatenation of n, applied m times. n * 1 then means to concatenate one n with nothing, yielding n, ie. the identity.


But that's a different kind of concatenation, not the concatenation of m and n.


All right, I'm game. How about function compositions? :-)


Not only true but faster because less time spent debugging.


And it's faster and easier to add new features because you can refactor without fear.


I don't refactor with fear in my Rails apps since they have pretty good test coverage. I'm not saying it's perfect, but I've never had slow development because I wanted to refactor in this context.


It's been slower for me, personally. I write half the tests in Haskell than I had to in Python which means less updating of tests as requirements change. It won't feel slow to you until you've written productive (beyond beginner) software in Haskell.


Only if you don't count debugging whatever the fancy type system is doing vs. what you need the behavior to be


What does this mean? I don't think most Haskell users spend a lot of time debugging the type system.


New Haskell developers spend a bit of time figuring out why the types of an expression aren't what they think they are, especially when wading into using some of the libraries with more sophisticated use of types.


Now, It's "New Haskell developers" vs "New Ruby/RoR developers". Isn't it?


I'm not certain what you're asking. If you mean it's unfair to compare experienced Ruby developers to new Haskell developers I agree, I was just explaining where the sentiment was coming from (insofar as it was legitimate).


Well, New Ruby developers doesn't have the same problem. They can move much faster than the initial uphill struggle that is Haskell.

Essentially, there are three sitations:

a) Everything is of the same difficulty. b) Haskell is more difficult than Ruby. c) Ruby is more difficult than Haskell.

I'd say (b) is a much saner conclusion.


You're assuming that difficulty is a single constant, which is definitely not the case. The real state of things is that Haskell is more difficult than Ruby to get really good at, but the actual work of developing things in Ruby is much more difficult than developing things in Haskell. This is because when you develop things in Ruby, you spend a lot of time debugging heisenbugs due to the total lack of referential transparency.

Accordingly, yes, newcomers to Haskell will probably have difficulty understanding what the type system is telling them, and this will slow them down a bit. But analogously, newcomers to Ruby (especially those using a heavyweight framework) will have difficulty figuring out why their application is doing what it is, and this will slow them down a lot.

(Source: I've worked professionally in both languages.)


Today I learned that a bug of which you can only know either its position or its velocity but not both to any significant degree, is a heisenbug.


I'm not sure if you're joking, but Heisenbug is used to mean "bug that changes when you try to observe it".


I think You are assuming that the learner here is already a (imperative or OOP categorized) programmer who is willing to learn these two languages.

For ruby still there would be some topics you need to know about before trying to learn language itself, if you are just starting out.


"You are assuming that the learner here is already a (imperative or OOP categorized) programmer who is willing to learn these two languages."

To be fair, that is not an uncommon situation.


agreed


How do you plan to deploy your backend? Are there tools to do it? Is it just rsyncing a cabal sandbox to another machine? What about compiling and stuff? (I've barely made my way through LYHGG.)


You can deploy Snap apps to Heroku pretty easily.

https://github.com/begriffs/heroku-buildpack-ghc


So we started with a git subtree merge of all the dependent projects and then a script to build a docker container, with physical infrastructure managed by ansible. It now looks more like we're going to use NixOs and NixOps - which are awesome!


I used to just scp the binary up to the servers. They don't need any haskell stuff installed or anything like that. Recently I made it so they grab the latest binary off of S3 on bootup and when I run an update script. So now I just upload the binary to S3 instead.


Are there any open source Snap projects that are good to learn from the code?


There is a list of some people using Snap here[1] and some of them are open source. The book also has approximately 8 pre-coded projects that come with it and correlate to the chapters.

[1] http://snapframework.com/faq#is-anyone-using-snap-in-product...


Are there (good) tools to help with refactoring Haskell? To me this seems like one of the benefits of a statically typed language (I've almost entirely worked in Perl).


Not as good as for example for C#, but not as bad as for example Ruby.

I have a plugin for Sublime that complains when something is broken, or a dependency is missing. The typesystem is so strong that usually when it compiles, it works.

So my process for refactoring is basically changing typesystems, and having the compiler check my changes until it works again.

Note that this thinks of Ruby as bad only in IDE aspect. Refactoring Ruby is actually quite enjoyable as Ruby is so friendly to unit testing. You just move your code and run your tests again.


Look up [HaRe the Haskell refactorer]


There's a new web library that extends Scotty with basic session and authenticiation support, called Spock.

I used it for a personal project of mine, which is creating an rss reader resembling the now dead iGoogle (which I loved), and although I had to read a lot of source code to get it to work, I really enjoyed how I worked with it, after figuring out the patterns on how to use it.

It definitely isn't finished, it could use some love by some eager developers, but in my opinion it has the potential to be the best framework out there.

- It extends scotty, so defining routes and control logic is fast and simple - It does not cage you in with a template language, or libraries that you don't want thrown in your face.

For example, I used Scotty with my own templating language I made for fun (hemplate), as well as a validation library I made, which I hope to finish in the near future, (after I get a job).

http://hackage.haskell.org/package/Spock


Cool, this is really good for Snap. I heard good things about Snap, but a major reason I went to Yesod instead was that it had a book that I could work through (For a Haskell beginner like me, having some structure was important).


I was about to use Yesod instead also, then I came across OP's book.


Finally! Snap is a great framework but it's been missing a good guide for a while.


I just started playing with Scotty while I learn, but I'm beginning working on a web app in Haskell and was leaning towards using Snap. I'll almost certainly pick this up. That new IO manager is a beautiful thing.


Please consider changing the title font. It is very hard on my eyes.


As long as we're talking about the appearance, I had to zoom out to be able to see the text with Firefox 27, and then stuff started moving around like some pieces of it were centered with different methods or something.


And also the color contrast.


The typography makes my eyes bleed.


Did you have problems with extremely ugly typefaces in the sample chapter? I had horrible typefaces with bold ligatures. It seemed as if my hinting and sub-pixel rendering had stopped working. There were many errors and warnings in the debugging console as well.


How does this compare with Meteor? I love Haskell, and if Snap can do the same kind of magic that Meteor does, I'll switch.


Meteor is more for front-end right? I think Snap is mostly for the backend portion of that, however there are some Haskell to Javascript libraries which may enable functionality you get with Meteor (as well as the type safety most know and love).


Meteor is for both ends at the same time. Most of your code on front end and back end is shared, including database queries, in a safe way.


Check out Fay (Haskell to JS). You can scaffold up a test site with Yesod where it integrates with Fay.

https://github.com/yesodweb/yesod-scaffold/tree/postgres-fay

It's not quite Meteor (then I dont believe it is so great), but works today and gives you Haskell from front-to-back.

The Haskell Center IDE of FPComplete is build with Yesod and Fay -- and that is a serious application.


While nice it's definitely not for a beginner. This enormous scaffold pulls in so many different things that it'd take a very long time to figure out.


Well, so does Rails. I was (and still am) a beginner with this, but i got productive fairly quickly.


Is there a site analogous to the Rails Tutorial e-book, but for Haskell?


why anyone would want to build with snap leaving RoR behind.


Yes, leaving RoR behind is certainly one reason for some people to use snap. But even for people who didn't fall into the rails trap, haskell is much nicer for web development than most languages (PHP, python, java, C#, etc).




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: