简体   繁体   中英

GHC IO compilation error

I have a problem compiling the following code on GHC 6.12.3 and I don't understand why.

The purpose of function test2 is to return a function that uses an integer to get a string element from a list (the list is created from the first nodes from a pair-list).

The IO bits is needed as test2 is used by another function using IO.

type PairList = [(String, String)]

test1 :: [String] -> Int -> String
test1 list x = list !! x

test2 :: PairList -> IO (Int -> String)
test2 pl = do
    f <- [fst x | x <- pl] :: IO [String]
    return test1 f

GHC gives me this error:

Test.hs:8:6:
    Couln't match expected type 'IO [String]'
        against inferred type '[a]'
    In a stmt of a 'do' expression:
        f <- [fst x | x <- pl] :: IO [String]
    In the expression:
        do { f <- [fst x | x <- pl] :: IO [String];
            return test1 f }
            ...

Edit:
If you want to do this directly (you need extra IO while computing test2 ), you can do something like

test2 :: PairList -> IO (Int -> String)
test2 pl = do
     putStrLn "Hi Mum!"
     return (test1 [fst x | x <- pl])

Your original code didn't work because when you did f <- [...] , you were using the list monad as if it were the IO monad.

Purely as an example, you can use that like this:

myactions = do
   putStrLn "Please enter a list of (String,String) pairs:"
   pl <- readLn -- which you'd have to write, or derive Read and use readLn
   f <- test2 pl
   putStrLn "please enter a number:"
   n <- readLn
   putStrLn $ f n

Which would give you behaviour like

*Main> myactions
Please enter a list of (String,String) pairs:
[("hi","yes"),("oops","bye")]
Hi Mum!
please enter a number:
1
oops

Original answer:

I don't think you need the IO bits:

type PairList = [(String, String)]

test1 :: [String] -> Int -> String
test1 list x = list !! x

test2pure :: PairList -> (Int -> String)
test2pure pl = test1 [fst x | x <- pl] 

This compiles fine, and gives results like

test2pure [("a String","ignored"), ("Another String","bye!")] 0
"a String"

If you want to use it in IO, you could use it like this:

myactions = do
   pl <- readLn
   let chosen = test2pure pl 3
   putStrLn ("3: " ++ chosen)

Or you could write

test2IO :: PairList -> Int -> IO String
test2IO pl n = return (test2pure pl n)

If you really want to use IO () as a return type you can fix the compile error like this:

test2 pl = return $ test1 [fst x | x <- pl]

As AndrewC said in his answer, you probably don't need monads in this function.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM