2

这有效:

c <- fmap lines (readFile "d:\\tmp\\h.txt")  
let h = map (read :: String -> Int) c 

而那些没有编译的那两条线的“叠加”

fmap (read :: String -> Int) $ fmap lines (readFile "d:\\tmp\\h.txt")

它会产生错误:

互动:1:36:
    无法将预期类型“Char”与实际类型“[Char]”匹配
    预期类型:字符串 -> 字符串
      实际类型:字符串 -> [字符串]
    在`fmap'的第一个参数中,即`lines'
    在 `($)' 的第二个参数中,即
      `fmap 行 (readFile "d:\\tmp\\h.txt")

为什么它不编译以及如何在一行中执行此操作?我想要的是实现python的简单性

[int(i) for i in open("d:\\tmp\\h.txt")]
4

3 回答 3

11

你离开map了你的“叠加”(组合):

h <- fmap (map (read :: String -> Int)) $ fmap lines (readFile "d:\\tmp\\h.txt") 

您可以将其简化为

h <- fmap (map (read :: String -> Int) . lines) (readFile "d:\\tmp\\h.txt") 

如果您import Control.Applicative在源文件的顶部放置一行(或者:m +Control.Applicative如果您以交互方式使用 ghci,则输入),您可以使用<$>运算符而不是fmap让它看起来更清晰。(它们的作用完全相同,只是拼写不同。)

h <- map (read :: String -> Int) . lines <$> readFile "d:\\tmp\\h.txt"

最后,如果您确实需要类型签名,您可能会发现它在行尾看起来更清晰。

h <- map read . lines <$> readFile "d:\\tmp\\h.txt" :: IO [Int]
于 2012-04-20T15:50:13.547 回答
9
[int(i) for i in open("d:\\tmp\\h.txt")]

将计算与动作分开:

return . map read . lines =<< readFile "d:\\tmp\\h.txt"
于 2012-04-20T15:53:04.873 回答
8

关于。你的第二个问题: usingApplicative会使它更具可读性:

map read . lines <$> readFile "file"

您可能能够避免给出read类型签名,具体取决于您的代码的其余部分,这将是可取的

于 2012-04-20T16:00:37.813 回答