0

我在 GHC 6.12.3 上编译以下代码时遇到问题,我不明白为什么。

function 的目的test2是返回一个函数,该函数使用整数从列表中获取字符串元素(列表是从对列表中的第一个节点创建的)。

IO 位是需要的,因为test2另一个使用 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 给了我这个错误:

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 }
            ...
4

2 回答 2

1

编辑:
如果您想直接执行此操作(计算时需要额外的 IO test2),您可以执行类似的操作

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

您的原始代码不起作用,因为当您这样做时f <- [...],您正在使用 list monad,就好像它是 IO monad。

仅作为示例,您可以像这样使用它:

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

这会给你这样的行为

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

原答案:

我认为你不需要这些IO位:

type PairList = [(String, String)]

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

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

这编译得很好,并给出了类似的结果

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

如果你想在 IO 中使用它,你可以这样使用它:

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

或者你可以写

test2IO :: PairList -> Int -> IO String
test2IO pl n = return (test2pure pl n)
于 2012-11-14T23:12:10.190 回答
0

如果你真的想IO ()用作返回类型,你可以像这样修复编译错误:

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

正如 AndrewC 在他的回答中所说,你可能在这个函数中不需要单子。

于 2012-11-14T23:26:52.890 回答