Comparing Haskell Web Frameworks
edofic.com
edofic.com
I experimented with it at one point and tried to change a form field from required to optional. Boom! The whole application wouldn't compile...
The properties of the form are reflected in the type system and changing required to optional changed the type. That means I had to track the effect through the application and everywhere that just assumed the data was there had to be updated to handle both cases.
It was so restrictive and confusing I gave up for the time being (until I learn Haskell better), but it was an eye-opening glimpse of the power of types.
While it might not be as instantly gratifying and being able to refresh and see the page is still working, in the long run it saves a lot of headache.
ghc -fdefer-type-errorsType errors don't require such a mental cost. Once you learn how to actually read the error messages it becomes almost brain-dead simple. Compile, jump to the error message (hopefully your editor can help here), fix, recompile.
it breaks the creative flow, it prevents experimentation.
I disagree. What prevents experimentation is the fear of the unknown regression. Strong types give you the reassurance you need to boldly refactor without worrying that you'll miss something.
The one place I wish I had better type safety in Snap is the SQL level. Yesod has Persistent which you can use with Snap but Persistent follows the same "black magic" design principles. I really wish there was a tool that handled PostgreSQL-specific query type checking and migration and that's it. No JSON/noSQL to SQL abstraction etc (which is cool if you want it but just a lot of if you don't). Once I pick a DB I don't want to constantly be generalizing away from it which is a conceptual overhead.
Coming from a background of web dev'ing in Python and PHP, I've come to absolutely love Yesod. What I love most about it is that when it compiles, I'm 99% sure it works the way I intended it. This is a huuuuge plus, since I've been used to always having to test in runtime, which adds a lot of overhead and possibility for oversight.
This might just be me falling completely in love with Haskell and type inference (not just static typing, Java -.-..), but I'd wager that for any larger codebase/project, the gain from the time saved debugging, would make Haskell (and IMHO Yesod) the optimal choice.
1. http://www.haskell.org/haskellwiki/Web/Comparison_of_Happsta...
A relatively complete listing of resources comparing the three major framework/libraries. A lot of this information is outdated, sadly.
2. http://stackoverflow.com/questions/5645168/comparing-haskell...
A SO question about comparing Snap and Yesod where both maintainers chime in. The major point of talking here is the Yesod style "Template Haskell" configuration.
3. http://www.reddit.com/r/haskell/comments/l0fne/what_should_i...
A similar question posed to /r/haskell with a great comment by yogostoth demonstrating Yesod.
4. http://softwaresimply.blogspot.com/2012/04/hopefully-fair-an...
A relatively balanced view comparing the three feature by feature. Again a bit outdated, but well-informed.
5. http://softwaresimply.blogspot.com/2012/12/haskell-web-frame...
And finally my favorite summary of the whole thing: the Web Framework matrix which considers each as a web programming embedded DSL and talks about their relative merits in a 2x2 table.
If I jump ship from Scala + Play framework to Haskell, Yesod will be my first choice, batteries included and then some.
Anyone know if a Haskell IDE is in the works? Certainly would help to be able to mouse hover-view type, or mouse click-go to source declaration a la Eclipse/IntelliJ/Visual Studio, etc., particularly for beginners, imagine that's a pretty big time sink in learning the language...
Also, any decent Haskell IDEs out yet? I'm using emacs purely for the syntax highlighting. I tried leksah but I gave up trying to configure it properly on my box.
What I get from that is my code is checked for style/compile errors everytime I save with ghc-mod and hlint. There's also commands to output the type of a function, run haskell code in VIM etc.
Note that you need ghc-mod installed for syntastic to take effect though.
[0] https://github.com/scrooloose/syntastic [1] https://github.com/dag/vim2hs
lalala :: f g Int -> m q -> z ()
lalala = undefined
and then just check and see if your logic holds water. Then, slowly fill in the implementations and use -XImplicitParams and ?f or 7.8 type holes and _ as placeholders that GHC will tell you the goal types of.Reflect as much information about side effects into your types as possible. Write new typeclasses to encapsulate smaller APIs like
class Teletype m where
writeLine :: String -> m ()
readLine :: m String
instance Teletype IO where
writeLine = putStrLn
readLine = getLine
echo :: Teletype m => m r
echo = forever $ readLine >>= writeLine
Then now we know what subset of IO `echo` actually uses.Generally, the type system is your friend and used correctly it lets you write a shitty first draft of your program elegantly and quickly and then get to the hard part of typing it out later.
If foo is giving you problems, write it as
foo :: (the type you think it should have)
foo = undefined
If it compiles you at least know your type is right. Then, leaving the type annotation in place, replace undefined with a more useful expression. (Soon we will all be using Type Holes instead of this trick.)I like hdevtools for mark-errors-on-save. I don't know if there's an emacs hook for it, but it's emacs so probably.
If you're talking about debugging after it compiles... I'm still working on that. I spent part of this past weekend digging into QuickCheck.
Additionally, Yesod relies heavily on quasiquoting and template haskell which can lead to some very cryptic code and errors. I generally prefer Snap for this reason and many others.
Eg. I had some problem where a Data.Text was being passed into a function where Data.Text.Lazy was expected (Network.Mail.Mime.simpleMail for the record). The error message was deep in the internals of Data.Text.Lazy rather than in my code. I had to play a ridiculous pecking game of using undefine on each time I use Data.Text in turn in order to find which particular Data.Text was causing the error and then explicitly force one particular argument type to be a Data.Text.Lazy. I didn't feel like the compiler helped me at all.
Stepping through a program linearly doesn't seem possible (though not entirely sure why not) so I have no intermediate or step through capability. I also can't (normally) just stick in a println in the middle of a function or view the data structures at any particular point of the program. These are two tools I use all the time with Java and C#, but in Haskell I am rendered blind.
For a simpler project, I've used a small subset of Snap. Well, the HTTP side was simpler: it was a game with the front-end completely in JS, and the server in Haskell; all Snap did was shunt JSON back and forth through a few routes for creating a new game, getting the updated game state, posting a move, etc.
Both are nice, depending on what you need, but for your average Django or RoR developer, Yesod gives the most bang for the buck in terms of learning a completely different paradigm.
[0] http://happstack.com/page/view-page-slug/9/happstack-lite [1] http://happstack.com/docs/crashcourse/index.html [2] http://www.yesodweb.com/book
It's just like using Sinatra or Express. It doesn't provide any url type-safety or magic, but that is also why it is easier to use.
One more step Please complete the security check to access edofic.com
Google Cache works though.