无法在Haskell

时间:2017-01-21 10:45:42

标签: haskell

我写了这个简单的函数,它接受两个文件名(String),并将第一个文件的内容写入第二个文件,将toUpper应用于每个字符。

import Data.Char

ioFile f1 f2 = do
            s <- readFile f1
            sUp <- [toUpper c | c <- s]
            writeFile f2 sUp

但是翻译会引发错误

Couldn't match expected type ‘IO String’ with actual type ‘[Char]’
In a stmt of a 'do' block: sUp <- [toUpper c | c <- s]
In the expression:
  do { s <- readFile f1;
       sUp <- [toUpper c | c <- s];
       writeFile f2 sUp }
In an equation for ‘ioFile’:
    ioFile f1 f2
      = do { s <- readFile f1;
             sUp <- [toUpper c | c <- s];
             writeFile f2 sUp }

如何将s用作[Char]代替IO String

2 个答案:

答案 0 :(得分:2)

你无法绑定纯粹的&#39;像sUp <- [toUpper c | c <- s]这样的值。请注意,与接受的答案所表明的不同,这并不意味着您无法为其命名。首先,return函数将纯值提升为IO(或任何monad,但我们现在正在IO),所以{ {1}} 工作。还有let语法的变体,它几乎就是这样做的:sUp <- return [toUpper c | c <- s]

答案 1 :(得分:0)

第二行不是IO Monadic操作,它只是列表理解,所以你应该把它写成:

import Data.Char

ioFile f1 f2 = do
            s <- readFile f1
            writeFile f2 [toUpper c | c <- s]

Haskell社区的一个重要部分32x32,因此更愿意看到:

ioFile f1 f2 = readFile f1 >>= \s -> writeFile f2 $ map toUpper s

甚至更短:

ioFile f1 f2 = readFile f1 >>= writeFile f2 . map toUpper

使用considers do harmful将给定函数(在本例中为toUpper)应用于给定列表的每个元素并生成结果列表。 map :: (a -> b) -> [a] -> [b]非正式地等同于在左monad的“结果”上调用给定的右操作数函数。所以c >>= f相当于:

do
    x <- c
    f x