在Haskell中使用do语句

时间:2018-04-25 13:52:08

标签: haskell io monads

最后学习如何在Haskell中使用monad!

我想阅读文件testInput,删除第一行,将函数waffles应用于其他所有行,并将结果保存到文件output.txt中。

我写了以下代码:

main = do
    contents <- tail . fmap lines . readFile $ "testInput"
    result <- fmap waffles contents
    writeFile "output.txt" $ concat result

waffles row col = (row - 1)*(col - 1)

可悲的是,编译器抱怨道:

waffles.hs:3:41:
    Couldn't match type ‘IO String’ with ‘[String]’
    Expected type: FilePath -> [String]
      Actual type: FilePath -> IO String
    In the second argument of ‘(.)’, namely ‘readFile’
    In the second argument of ‘(.)’, namely ‘fmap lines . readFile’

waffles.hs:5:9:
    Couldn't match expected type ‘[b]’ with actual type ‘IO ()’
    Relevant bindings include program :: [b] (bound at waffles.hs:2:1)
    In a stmt of a 'do' block: writeFile "output.txt" $ concat result
    In the expression:
      do { contents <- tail . fmap lines . readFile $ "testInput";
           result <- fmap waffles contents;
           writeFile "output.txt" $ concat result }
    In an equation for ‘program’:
        program
          = do { contents <- tail . fmap lines . readFile $ "testInput";
                 result <- fmap waffles contents;
                 writeFile "output.txt" $ concat result }
Failed, modules loaded: none.

我发现这个错误非常令人生畏。你能帮我调试一下吗?

我也很感激代码风格的建议!

编辑:我忘了拆分文件的行并将它们转换为整数。我尝试解决如下问题:

main = do
    contents <- tail . fmap lines . readFile $ "testInput"
    contents <- fmap read . words contents
    result <- fmap waffles contents
    writeFile "output.txt" $ concat result

waffles row col = (row - 1)*(col - 1)

但这只会引入更多令人困惑的编译器错误。

1 个答案:

答案 0 :(得分:4)

import keras.backend as K def customLoss(yTrue,yPred): create operations with yTrue and yPred - yTrue = the true output data (equal to y_train in most examples) - yPred = the model's calculated output - yTrue and yPred have exactly the same shape: (batch_size,output_dimensions,....) - according to the output shape of the last layer - also according to the shape of y_train all operations must be like +, -, *, / or operations from K (backend) return someResultingTensor 语句中的第一行失败,因为您尝试在do上使用tail。您需要IO [String] fmap函数:

tail

现在您需要一种方法来从contents <- fmap tail . fmap lines . readFile $ "testInput" -- or.... contents <- fmap (tail . lines) . readFile $ "testInput" 获取所有其他行。您可以为此定义一个简单的contents函数:

everyOther

现在你可以将它链接到第一行的everyOther :: [a] -> [a] everyOther (x:_:xs) = x : everyOther xs everyOther _ = []

fmap

contents <- fmap (everyOther . tail . lines) . readFile $ "testInput" 的{​​{1}}函数似乎与我认为的类型签名不相关。尝试从类型签名开始并从其中构建waffles。根据您的描述,您只是为函数提供其他所有行,因此它应该具有签名:

(row - 1)*(col - 1)

鉴于waffles的类型签名,您可以通过以下方式应用它:

waffles :: String -> String

输出中还有一件事:waffles会将所有线条混合在一起。您可能希望在那里使用换行符,因此您可能希望使用let result = fmap waffles contents 代替。

concat