f has the wrong type. It needs to return a value in the IO monad. For instance:

f: String -> IO String
f s = return (s ++ "!")

g :: IO String
g = readLn >>= f

You could also let f return a value of a type other than String, say:

f :: String -> IO ()
f = print

The type of >>= tells you this: Monad m => m a -> (a -> m b) -> m b. The second argument has type a -> m b. String -> IO () or String -> IO String both match that.

As a warning, readLn expects a Haskell value, and f requires that it be a string. So you have to type in a string the way you would in a program, as "Hello" or ['H', 'e', 'l', 'l', 'o'] or you'll get a parse failure.

On Thu, Jan 15, 2015 at 2:44 PM, Miro Karpis <miroslav.karpis@gmail.com> wrote:
Many thanks everyone,.. but I'm not so confident with monads. If I understand I could translate with them for example IO String to String? If this is true I'm having troubles to achieve this.

Here is my simple test (only to test the logic), which ends with error:

 Couldn't match type ‘[]’ with ‘IO’
    Expected type: IO Char
      Actual type: String
    In the expression: f a
    In the second argument of ‘(>>=)’, namely ‘(\ a -> f a)’



g = readLn
    >>= (\a -> f a)

f :: String -> String
f s_ = s_ ++ "!"



Cheers, Miro

On Thu, Jan 15, 2015 at 5:42 PM, Mike Meyer <mwm@mired.org> wrote:
On Thu, Jan 15, 2015 at 9:24 AM, Dimitri DeFigueiredo <defigueiredo@ucdavis.edu> wrote:
I would not say that the problem is with the guard check. The problem is with 'null'. It's type is

Prelude> :t null
null :: [a] -> Bool

So, it expects a list of something, rather than an IO of something, whence the complaint.


While that's the source of the error, the problem is the combination of the guard check and where to bind a value in the IO monad.

Guard checks must have a value of Bool. getDBRecord returns something of type IO [Int]. Where just binds a name, so you either need a way to extract the [Int] from the return value before binding it in the where, or a function of type IO [Int] -> Bool for the guard.

Note that this isn't an IO issue but a monad issue. There isn't a monad method that returns a value not in the monad, so you can't  write either of the two options above using monad methods. The best solution is the one already proposed - write a function from [Int] -> IO String, and use bind (>>=) on that function to handle things. You could also use the do sugaring of <- to get a less functional version.

The last option is to use the IO-specific function unsafePerformIO to write something like nullIO = null . unsafePerformIO. But it's called UNSAFE and tucked away in a module of similar operations for a reason. Using bind is much preferred.
 
On 15/01/15 09:51, Miro Karpis wrote:
Hi,

please is there a way to have guards with 'where' that communicates with IO? Or is there some other more elegant way? I can do this with classic if/else,...but I just find it nicer with guards.


I have something like this (just an example):


f :: Int -> IO String
f x
    | null dbOutput = return "no db record"
    | otherwise = return "we got some db records"
    where dbOutput = getDBRecord x


getDBRecord :: Int -> IO [Int]
getDBRecord recordId = do
    putStrLn $ "checking dbRecord" ++ show recordId
    --getting data from DB
    return [1,2]


problem is that db dbOutput is IO and the guard check does not like it:
 
Couldn't match expected type ‘[a0]’ with actual type ‘IO [Int]’
    In the first argument of ‘null’, namely ‘dbOutput’
    In the expression: null dbOutput



Cheers,
Miro


_______________________________________________
Beginners mailing list
Beginners@haskell.org
http://www.haskell.org/mailman/listinfo/beginners


_______________________________________________
Beginners mailing list
Beginners@haskell.org
http://www.haskell.org/mailman/listinfo/beginners



_______________________________________________
Beginners mailing list
Beginners@haskell.org
http://www.haskell.org/mailman/listinfo/beginners



_______________________________________________
Beginners mailing list
Beginners@haskell.org
http://www.haskell.org/mailman/listinfo/beginners