where 子句中的 IO
我以为我开始理解 Haskell 中的 IO 了,直到我遇到了下面的问题。
我有以下函数,它返回 IO Float 类型:
getFundPrice :: Int -> Int -> IO Float
getFundPrice fund date = do
priceList <- getFundPrice' fund date
let h = head priceList
return h
函数 getFundPrice' 使用 takusen 数据库并返回 IO [Float] 类型的列表。
我能够使用以下命令成功地使用 Hunit 测试 getFundPrice 函数:
p <- getFundPrice 120 20100303
assertEqual
"get fund price"
10.286
(p)
困扰我的问题是以下函数定义:
lastPos :: Int -> (Shares,Float) -> Period -> Fund -> (Shares,Float)
lastPos endDate begPos [] fund = (fst begPos, trnPrice)
where trnPrice = do
price <- getFundPrice fund endDate
return price
尝试编译时遇到的错误是“无法匹配预期类型 Float” '针对推断类型
IO Float'”
我认为 *price <- getFundPrice * 操作将为我检索价格,就像使用我的 HUnit 代码一样。
在 where 子句中使用 this 有什么不同?
I thought I was beginning to understand IO in Haskell until I ran into the following problem.
I have the following function, which returns type IO Float:
getFundPrice :: Int -> Int -> IO Float
getFundPrice fund date = do
priceList <- getFundPrice' fund date
let h = head priceList
return h
The function getFundPrice' uses the takusen database library and returns a list of type IO [Float].
I'm able to successfully test the getFundPrice function with Hunit using the following:
p <- getFundPrice 120 20100303
assertEqual
"get fund price"
10.286
(p)
The problem that is stumping me is the following function definition:
lastPos :: Int -> (Shares,Float) -> Period -> Fund -> (Shares,Float)
lastPos endDate begPos [] fund = (fst begPos, trnPrice)
where trnPrice = do
price <- getFundPrice fund endDate
return price
The error I'm getting when attempting to compile is " Couldn't match expected type Float' against inferred type
IO Float'"
I thought the *price <- getFundPrice * action would retrieve the price for me as it does with my HUnit code.
What's different about using this in the where clause?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果删除显式类型签名,您将看到正确的类型:
注意末尾的 IO Float 。您已将 trnPrice 定义为检索浮点值的 IO 操作。您没有执行该操作来检索该值!除了 IO monad 之外,您无法从任何地方执行该操作,而
lastPos
不在其中。您可以做的是:将所有
lastPos
提升到 IO 中。If you remove the explicit type signature you will see the correct type of:
Notice the
IO Float
at the end. You have definedtrnPrice
to be an IO action that retrieves a floating point value. You have not executed that action to retrieve the value! You can not execute that action from anywhere except for the IO monad, whichlastPos
is not in. What you can do is:Which lifts all of
lastPos
into IO.IO
monad 的问题是你永远无法摆脱不纯的污点。因为您的 getFundPrice 函数不是纯粹的,所以调用它的函数也不是纯粹的。您的函数必须具有以下类型:
如果有助于澄清问题,请在您的 where 子句中的
return
语句中将纯价格值包装回IO
中。没有办法1避免这样做 -IO
monad 被设计为不允许这样做。事实上,它与
where trnPrice = getFundPrice Fund endDate
1 完全相同,实际上有一个 后门,但使用它不是一个好主意
The thing about the
IO
monad is that you can never get rid of the impure taint. Because your getFundPrice function is not pure, nothing calling it can be pure either.Your function will have to have the type
If it helps clarify matters, in your where clause the
return
statement wraps the pure price value back up inIO
. There's no way1 to avoid doing this - theIO
monad is designed not to allow it.In fact it's exactly the same as
where trnPrice = getFundPrice fund endDate
1 actually there is a backdoor, but it's not a good idea to use it