【问题标题】:Haskell IO averaging function IO, pure vs unpure attemptHaskell IO 平均函数 IO,纯 vs 非纯尝试
【发布时间】:2013-03-06 22:04:41
【问题描述】:

我正在尝试编写一个程序,让用户不断输入数字并在输入负数后输出平均值 这是我保留pure separate from unpure 的尝试 有人可以给我修复此代码的提示,以及纯和不纯的分离提示。

getFloat :: IO Float
getFloat = do line <- getLine
              return (read line:: Float)  

“不纯的部分”

average :: IO Float
average = do x <- getFloat
             return((fst help x)/(snd help x))

“纯部分”

help x 
    |x>=0 = (x+sum1, 1+ counter)
    |otherwise = (sum1 , counter)
    where 
    sum1 = 0.0
    counter = 0.0

我收到此错误

.hs:45:26:
    Couldn't match expected type `(t0 -> Float, b0)'
                with actual type `t1 -> (t1, t2)'
    In the first argument of `fst', namely `help'
    In the first argument of `(/)', namely `(fst help x)'
    In the first argument of `return', namely
      `((fst help x) / (snd help x))'
Failed, modules loaded: none.

【问题讨论】:

  • 看起来更适合CodeReview
  • 这是一个愚蠢的方式告诉你help不是一个元组,所以应用程序fst help是错误的。
  • 我建议初学者编写更小的表达式,这样错误消息就不会那么混乱了。沿着let a = ..; let b = ...; return $ a / b 的行(替换;换行)
  • @Ingo:除非您还在那里添加类型签名,否则不会有太大帮助

标签: haskell io functional-programming


【解决方案1】:

让我们先看看你的代码有什么问题,然后再看看如何修复它。

函数getFloat 很好,完全按照你的想法做。

help 函数做你认为它做的事情。事实上,当输入一个值 x 时,它只返回元组 (x,1.0) 如果 x &gt; 0,否则返回 (0.0,0.0).. 你可以给它类型:

help :: Double -> (Double,Double)

而我猜你打算让它有这个类型

help :: [Double] -> (Double,Double)

你可以这样写你想要的版本:

help xs = (sum xs, fromIntegral (length xs))

在函数average 中有表达式fst help x,它的括号如下:(fst help) x。这就是您的错误消息的原因:您只能将 fst 应用于 (a,b) 类型的东西,但您试图将其应用于 Double -&gt; (Double,Double) 类型的东西,因此会引发错误。

如果我要编写这个函数,我可能会这样做:

import Data.List (takeWhile) -- take elements from a list while predicate is satisfied

avg xs = sum xs / fromIntegral (length xs)

main = do numbers <- fmap (takeWhile (>0) . map read . words) getContents
          return (avg numbers)

函数avg 是纯函数。函数takeWhile (&gt;0) . map read . words 也是纯函数,可以这样分解:

helper :: String -> [Double]
helper = takeWhile (>0) . map read . words

main = do numbers <- fmap helper getContents
          return (avg numbers)

这说明了一个一般原则 - 使用不纯代码输入和输出您将使用的值,并使用纯代码转换这些值。

【讨论】:

  • fmap (avg . helper) getContents
  • 是的,这是一种更简洁的书写方式!
  • 我想知道 OP 是否真的不想逐步累积结果,而不是使用列表。
猜你喜欢
  • 2016-03-20
  • 2013-02-01
  • 2014-06-16
  • 1970-01-01
  • 1970-01-01
  • 2023-03-14
  • 2019-03-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多