gpt4 book ai didi

haskell - 状态单子(monad) haskell

转载 作者:行者123 更新时间:2023-12-02 06:44:02 25 4
gpt4 key购买 nike

我想在 haskell 中使用 State Monad 编写一个计算平均值的函数这是我到目前为止写的代码

import Control.Monad.State
type MyState = (Double,Double)
media s (a,n)= ((a*n+s)/(n+1),n+1)

getAverage:: Double ->State MyState s1-> Double
getAverage s c=get >>= \s0 -> let (x,s1) =media s s0
in put s1 >> return x

我在 GHCI 中编译时遇到了这个错误,我一直卡在那里你能帮我理解哪里出了问题吗,提前谢谢你

最佳答案

您提供的代码出现此错误:

Couldn't match expected type `Double'
against inferred type `m Double'
In the expression:
get >>= \ s0 -> let (x, s1) = ... in put s1 >> return x
In the definition of `getAverage':
getAverage s c = get >>= \ s0 -> let ... in put s1 >> return x

这意味着表达式(“推断”)产生的类型与类型签名(“预期”)不一致。在这种情况下,getAverageState monad 中运行,因此类型签名不正确,因为它无法评估为非 monadic 类型。

除此之外,您的代码还有其他问题,即使在解决该特定问题后也无法编译。首先是一些文体问题,以使其更具可读性:

  • getAverage 有一个未使用的参数,它应该是 State monad 中的一个值,无论如何它都没有实际意义。
  • 使用 do 符号通常比使用 (>>=) 和 lambda 更清晰,尤其是对于 State 这样的东西。
  • 第二行的缩进令人困惑,因为 in 与 lambda 内部let 一起出现。

做出这些改变我们有这个:

getAverage s = do
s0 <- get
let (x, s1) = media s s0
put s1
return x

...这使得更容易发现下一个错误:media 的第二个参数是一个二元组,s1 只是一个数字,但是您正在尝试将两者都用于状态值。可能您想要的是将状态设置为 (x, s1),但仅返回 x

getAverage s = do
s0 <- get
let (x,s1) = media s s0
put (x,s1)
return x

这编译得很好,但仍然需要一些整理:

  • media 需要更新整个状态值,所以不用getting 和putting,只需使用modify 功能。
  • 返回值是状态值的第一部分,因此通过 get fmaping fst 更直接。

所以现在我们有这样的东西:

media :: Double -> MyState -> MyState
media s (a, n) = ((a * n + s) / (n + 1), n + 1)

getAverage:: Double -> State MyState Double
getAverage s = do
modify (media s)
fmap fst get

我们还可以注意到 getAverage 是做两件不同的事情,并将其拆分为单独的函数:

updateAverage:: Double -> State MyState ()
updateAverage s = modify (media s)

currentAverage :: State MyState Double
currentAverage = fmap fst get

getAverage:: Double -> State MyState Double
getAverage s = updateAverage s >> currentAverage

编辑:由于我忘记了实际从 monad 中取回结果的次要细节,因此将 updateAverage 替换为 getAverage Travis Brown 的 getAverages 函数将让它适用于我上面的代码。

关于haskell - 状态单子(monad) haskell ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3373794/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com