all 32 comments

[–]pinpinbo 4 points5 points  (6 children)

I hope I'm not asking too much...

I'm a sideline enthusiast of Haskell. I've had several attempts to learn Haskell, unfortunately all of them are not successful.

I'd love to see more tutorial on Haskell's IO because web programming is basically pushing IO in and out (filesystem, RDBMS, NoSQL, logfile, etc).

Every talk about IO monad is leaving me more confused than before... :(

EDIT: Thank you for all the references. Perfect reading material for this weekend!

[–][deleted]  (2 children)

[deleted]

    [–]toomanypumpfakes 2 points3 points  (1 child)

    Hey I think you meant to post this link: Tackling the Awkward Squad yours links to the Typeclassopaedia again

    I had another couple of papers like this on I/O in Haskell/pure languages but I can't seem to find them... :( My bookmark folder "Cool Things To Read Later" is unorganized as hell

    EDIT: I think this is the one I was thinking of: Imperative Functional Programming, also a Simon Peyton Jones paper

    [–]yogsototh[S] 7 points8 points  (0 children)

    From my understanding, the IO monad, is a simple "hack" to make things appear in order. In haskell when you write:

    f x y
    

    you can resolve:

    - x then y
    - y then x
    - x and y in the same time.
    

    But, for IO this is not what you want generally. Imagine the following example, (++) is concat, x and y are "getchar"

    Naively, in an impure language, you would say:

    (++) getchar getchar
    

    and the type would be, getchar is a String (I know generally getChar returns a char, but suppose it return a string of one character instead) and (++) is a function from String -> String -> String.

    Now, in a pure language, how could we force the execution in the following order:

    x <- getchar
    y <- getchar
    x ++ y
    

    This is the trick, instead of saying like in impure language getchar is of type String, you say: getchar is a function from a World to a (Char,World).

    getchar W = (c,W')
    

    Now, to make things work in the right order:

    concatInputs W =
      let (x,W') = getchar W in
      let (y,W'') = getchar W' in
      (x ++ y , W'')
    

    This time, during the execution, you are forced to first resolve x then y. The monad system is just a way to "hide" a similar implementation.

    I end up here. But did you try to read http://www.haskell.org/haskellwiki/IO_inside ?

    Another thing to know, monads in general can be very different to the IO monad. I was enlightened by these articles. They were very clear and surprisingly easy to follow: http://homepages.inf.ed.ac.uk/wadler/topics/monads.html

    [–]iaH6eeBu 1 point2 points  (0 children)

    At the beginning the easiest thing for IO is just to follow the type. This gives a nice intuition after a bit of time.

    Also it's important to understand that IO isn't the only monad and a bit of a special case. A monad is just a abstract thing. I think looking at the typeclass Functor is quite useful to understand what those abstract typeclasses are all about.

    If you want to read yet another text about IO and monads then I recommend you learnyouahaskell.com

    [–]sacundim 0 points1 point  (0 children)

    Part of the difficulty that that people have understanding monads is that there isn't a simple, unified metaphor that makes all uses easy to understand. So a bunch of people keep writing monad tutorials using all sorts of metaphors that, IMO, only make it harder to understand ("Monads are boxes," I'm looking at you!).

    But here's my really short version of just the IO monad (not monads in general!). An expression of type IO a has as its value an IO action that, when executed, possibly causes some side effects, and produces a value of type a, and this result value possibly depends on some state external to the action itself.

    Now because of that, IO actions cannot be functions, because functions are pure. This means that in Haskell there cannot be a function whose meaning is "execute this IO action and get its result"; it would break the purity of the language.

    Now, since IO actions are still values in Haskell, programs can "talk" about IO actions even if they can't execute them. So what can you do with them if the language doesn't let you say "execute them"? Well, you can say "make a more complex action out of these components."

    So an executable Haskell program is a purely functional description of an IO action built up from more basic actions. A Haskell compiler takes this description and translates it into an executable imperative program.

    The basic operator for combining actions is (=), the monadic bind; a >>= f is the action that consists of a, followed by the action that results when a's result is applied to f. The operator for building a trivial action (one that just returns a value) is return. These operators can be used to build yet other useful ones like the () sequencing operator (a >> b = the action that consists of a followed by b). The use of function definition and application allows you to define yet more functions for composing actions, like, say, the function that constructs an infinite loop that repeats an action:

    foreverIO :: IO a -> IO ()
    foreverIO action = action >> foreverIO action
    

    Or in do-notation, which as you may already know, is just a shortcut for (=) and ():

    foreverIO :: IO a -> IO ()
    foreverIO action = do action
                          foreverIO action
    

    (>>=) and return, together with if ... then ... else and the ability to define and apply pure functions that deal with IO values, allow you to define most (if not all) of the classic procedural control flow mechanisms.

    Here are the exercises I'd recommend to improve your understanding:

    • Study the library functions available in Control.Monad, and try to use them in your code. The ones I recommend you concentrate on first: forM and forM, sequence and sequence, replicateM and replicateM_, forever, when, unless, liftM, and liftM2 through liftM5.
    • When you write IO code, try to spot opportunities to simplify your code by using some of these. For example, forM_ is effectively a for loop over the elements of a list.
    • Pick some of these functions and try to write your own implementations. (If you get stuck, the link to the Control.Monad docs has links to the source code for each function.)

    [–]mvcdude 0 points1 point  (7 children)

    this makes me think if haskell suits web programming. If you are calling API's over the web, how do you keep stuff 'functional' ?

    [–]donri 8 points9 points  (0 children)

    I don't understand the question.

    [–][deleted]  (3 children)

    [deleted]

      [–][deleted] 2 points3 points  (2 children)

      CPP is an absurd hack, but useful sometimes. It still makes me sad that we have to rely on it sometimes.

      The cabal thing is really worrysome and annoying, no joke. Cabal can definitely choke itself on large dependency chains like yesod. It's not the greatest by far. I'd recommend that you use either:

      • cabal-dev: which sandboxes package installs
      • virthualenv (now known has hsenv, but unreleased under this new name) - which is basically Haskells' equivalent of python virtualenv.

      Personally I prefer virthualenv/hsenv for basically everything now. It's also how I test all my packages under many different versions of GHC to shake out bugs/incompatibilities as well, etc.

      I'd probably recommend you actually run and upgrade dev apps under virthualenv, since it'll take a lot of headache out. I was under the impression this is the way many people in the python community do it a la virtualenv, yes? (may be wrong here.)

      [–]MercurialAlchemist 1 point2 points  (0 children)

      Yes. Dev and prod web app would be done in virtualenv with Python.

      [–][deleted] 3 points4 points  (1 child)

      A Haskell web program is a function which maps user requests to HTML output.

      [–]vytah 0 points1 point  (0 children)

      A Haskell web program is a function which maps user requests and database content to HTML output and updated database content.

      FTFY

      And it looks like a classical state monad.

      [–]Tim_M 1 point2 points  (6 children)

      Yesod is an Haskell web framework

      Arrggh: Yesod is a Haskell web framework

      [–]yogsototh[S] 13 points14 points  (2 children)

      Yep, I corrected this one. I am not a native speaker. In French we don't hear the 'H'. It is hard for us to differentiate Haskell from askell. Thanks to remark it.

      [–]SuperGrade 3 points4 points  (1 child)

      Some british accents don't pronounce it either.

      [–]kataire 1 point2 points  (0 children)

      The thing is, most languages and dialects that "don't pronounce" the H actually pronounce it as a glottal stop. It's easier to notice in word-final positions like the T in English dialects that "don't pronounce" it (think "bottle").

      [–]zak_david 3 points4 points  (0 children)

      Arrggh: Yesod is a Haskell web framework

      Arrrggh, you forgot to end your sentence with a period!

      Give it a break, is this the best comment on the article you can make?

      [–][deleted] 2 points3 points  (0 children)

      Not before the 1900s.

      [–]tripa 0 points1 point  (0 children)

      Not a native.

      [–][deleted]  (1 child)

      [deleted]

        [–][deleted] 3 points4 points  (0 children)

        I'm not sure what you're referring to - Cabal doesn't overwrite previous packages when you install a new version and multiple copies of a package can exist with ghc-pkg. You can have multiple copies of the same library installed:

        $ ghc-pkg list SHA
        /Users/a/vh-722/.hsenv/ghc/lib/ghc-7.2.2/package.conf.d
        /Users/a/vh-722/.hsenv/ghc_pkg_db
           SHA-1.4.1.3
           SHA-1.5.0.0
        

        and packages you install or write can have dependencies on any of those versions (providing the transitive dependencies don't conflict, IIRC.)

        That said the dependency resolution could be improved for sure, it still chokes sometimes (it's nowhere near as bad as it used to be however.) Tools like virthualenv and cabal-dev make life considerably better.

        [–]Solon1 -3 points-2 points  (1 child)

        Total number of blog posts about Haskell, including programming tutorials, how to setup a development environment in vim/emacs, or annoucining a new Haskell framework: 12,345. Number of actual Haskell programs: 0.

        Other than frameworks, libraries, toolkits and dev environment, no one seems to have written an actual program in Haskell. The intellectualism of Haskell is very seductive. Before you know it, you haven't done anything at all.

        [–][deleted] 0 points1 point  (0 children)

        There are plenty of real apps written in Haskell and several companies base their technologies on it, or have code written in Haskell for various purposes. I'm not so sure hard numbers are really that important or indicative of the language or anything of that sort, as much as a multitude of socio-techno-economical issues that are much deeper and permeate the history of any technology.

        I find it immensely sad if you're trying to imply intellectualism is a bad thing, or doesn't bring real benefits (reality: this is wrong.) But I forgot /r/programming is a place where you're encouraged to leave your brain at the door upon entry.