为什么这个功能组合是非法的

时间:2012-04-20 15:37:58

标签: haskell syntax

这有效:

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")

它会产生错误:

interactive:1:36:
    Couldn't match expected type `Char' with actual type `[Char]'
    Expected type: String -> String
      Actual type: String -> [String]
    In the first argument of `fmap', namely `lines'
    In the second argument of `($)', namely
      `fmap lines (readFile "d:\\tmp\\h.txt")

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

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

3 个答案:

答案 0 :(得分:10)

您将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行(如果您以交互方式使用ghci,则输入:m +Control.Applicative),您可以使用<$>运算符代替{ {1}}让它看起来更干净。 (他们做同样的事情,他们的拼写不同。)

fmap

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

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

答案 1 :(得分:9)

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

将计算与行动分开:

return . map read . lines =<< readFile "d:\\tmp\\h.txt"

答案 2 :(得分:8)

重。第二个问题:使用Applicative会使其更具可读性:

map read . lines <$> readFile "file"

您可以避免提供read类型签名,具体取决于您的代码的其余部分,这将是更好的