Haskell, MongoDB driver, >>=, and <<=

EDIT: Wanted to get this in real quick before the forum moderator trolls shut this down (they've been retroactively going through my posts which are months old, down voting them, then closing them). The problem is either the driver or the docs, because the example code has the same issue when I run it.

I'm trying to evaluate Haskell in terms of using it with MongoDB. I've tried to write my own simple program to do simple things to a database using examples on this driver page https://github.com/TonyGen/mongoDB-haskell . I can get as far as opening a connection and even making inserts into a database (I checked the DB, everything makes it inside). The problem I'm running into is, once I open a connection and do something, I can't get the Haskell program to "come back" to the interpreter, print some value, or do anything else. This may be the wrong word, but I think the program is essentially "locked."

Not sure, but I believe that I'm not terminating correctly inside the "do" notation, thus I think it's just sitting there. In looking at the examples on the driver page, I notice that it makes use of operators such as >>= and <<=. I suspect (not sure) that I need one or both of these operators to terminate from the "do," or somehow finish what I'm doing.

I'd just like some clear examples of an operator or operators I need and how to use them to finish this "do" and get back to the interpreter, possibly with some return value like "finished" or whatever. The explanation should be in very basic, practical, plain-spoken, matter of fact terms, spoken in an almost unsophisticated or juvenile way. The explanation should not focus on how it does what it does, why it does what it does, or what goes on inside this operator or operators. It should just be how to use it to do "such and such."

An example (wrong in what it instructs, correct in how the instruction should look):

"See that thing that looks like a backwards arrow (<<=)? That's called the 'backwards arrow operator.' Any time we want to stop execution from a do, and shoot information back from the monadic world to the world of pure Haskell, we use that operator to do it. How it works is, you stick the information you want to shoot back on the right hand side. On the left, you stick...."

I don't want any explanation of what a monad is, how to use a monad, what goes on inside a monad, how a monad works, etc. I've consulted the literature numerous times.

I also don't want explanations of what these operators such as >>= or <<= are, or how they work, what they are doing, etc. I want explanations of HOW TO USE THEM (if needed), just not the theoretical (or other) stuff.

I've already scanned this website and other documentation but couldn't find what I was looking for in the format I wanted it (described above).


{-# LANGUAGE OverloadedStrings, ExtendedDefaultRules #-}

import Database.MongoDB
import Control.Monad.Trans (liftIO)

main = do
    pipe <- runIOE $ connect (host "")
    e <- access pipe master "test" run
    close pipe
    print e

run = do
    -- missing something here?  tried return "finished" and other things

test_insert = insertMany "blah" [ stuff... ]


So, the request is to explain the bind operator (>>=) -- the central operation of the Moand class -- without getting into Monads. Why not, I love a challenge.

Start with >> it works like a semicolon in other languages. It lets you stick two actions in one line. This is a lie, but you don't want to face the truth. (The truth involves understanding the difference between actions and functions.)

But what happens if we need to use the result of one action in the next? The >>= operator take the result of one action and feeds it as the argument to the next one (=<< does the same thing only backwards).

So, allTeams >>= printDocs "All Teams" is the same as

   teams <- allTeams
   printDocs "All Teams" teams

And, allTeams = rest =<< find (select [] "team") {sort = ["home.city" =: 1]}

allTeams = do
   cursor <- find (select [] "team") {sort = ["home.city" =: 1]}`
   rest cursor

In fact, you can translate any do block into a set of >>= equations and any set of >>= equations into a do block mechanically.

At this point, you should really be confused about why the need for such convoluted syntax with actions and also be running into some really obtuse type errors. When you have become too frustrated by these things I will lay before you two choices:

  1. Admit that you need to actually know a little something about why haskell is very different from imperative languages; need to understand the differenc between actions and functions; and figure out that this isn't just all about a lousy syntax, or
  2. Decide that haskell has nothing interesting to offer you and return to coding in Prolog.

Should you choose option 1 Here is where you need to start.

Update debugging

So what we know is that the insertMany action hit the database. Did it actually return. I note that you are using master access mode which means that access is going to wait until MongoDB gets back to it with confirmation that the data is written.

There is also that close pipe action. This could block in theory. lets do this the cheap way and just add some print statements:

main = do
    putStrLn "Start --"
    pipe <- runIOE $ connect (host "")
    e <- access pipe master "test" run
    liftIO $ putStrLn "before close pipe"
    close pipe
    print e
    putStrLn "\n Finished"

run = do
    liftIO $ putStrLn "before insert"
    liftIO $ putStrLn "after insert"

test_insert = insertMany "blah" [ stuff... ]

From what you describe we should see

Start --
before insert
^C -- we got stuck here

If this is the case, I will need to see stuff...

If you get farther through the program (my gut says you will see "after insert" but not "before close pipe") then we need to talk about whether haskell is communicating correctly with Mongo. Even if it recorded the insert correctly, the pipe may still be "on hold" waiting for a synchronizing event that is not coming.

We can then believe that it is not incorrect use of haskell but incorrect use of the MongoDB library and ask another SO question with that in mind.

Need Your Help

Using a PHP GET server

php android mysql objective-c json

I'm trying to create a mobile application and I was wondering if the following is both safe and fine to do so.

Mockito and Junit tests run in isolation but fail when run together

junit mockito

I have been encountering a strange issue. My test cases have one failing test, the welcometest. However, if I run the same in isolation, it runs perfectly. I am new to JUnit and have no idea why this