Haskell 中的值被丢弃
Value is discarded in Haskell
我不明白为什么会这样:
module Main where
import Control.Monad.Reader
data Config = Config Int
getA :: (Monad m) => ReaderT Config m Int
getA = do
Config a <- ask
return a
readConfig :: Config -> IO Int
readConfig = runReaderT getA
main :: IO ()
main = do
print "Start"
let a = Config 2
b <- readConfig a -- Will be printed
print b
let c = Config 4
print <$> readConfig c -- Silence, nobody complains..
print "Done"
结果是:
"Start"
2
"Done"
为什么 print <$> readConfig a
是空的?即使 -Wall
也没有人抱怨这个...
(我在 godbolt 中尝试了 diff ghc 版本,但结果保持不变)
编辑:
好的,我找到了问题的等效描述,感谢@chi和@David:
module Main where
test :: IO ()
test = do
print "test"
return ()
main :: IO ()
main = do
let t = test -- equivalent to print <$> readConfig c, is IO (IO ())
test -- equivalent to print b is IO ()
现在,我只想知道为什么 let t
不评估。根据我的直觉,以前很明显,但现在不明显了......但是有答案(esp. from Tanner Swett)
GHC 8.10.3 确实用 -Wall 抱怨这个(在我将你的代码中的 initConfig
更改为 readConfig
之后):
A do-notation statement discarded a result of type ‘IO ()’
Suppress this warning by saying ‘_ <- print <$> readConfig c’
您有 readConfig c
类型 IO Int
。然后你 fmap print
,给出类型为 IO (IO ())
的东西。由于结果未绑定到 do 块中的变量,因此将其丢弃。
在 fmap 的类型 Functor f => (a -> b) -> f a -> f b
中,我们有 f
是 IO
,a
是 Int
,b
是 IO ()
.所以它与 (Int -> IO ()) -> IO Int -> IO (IO ())
.
类型一起使用
这可行:
printAction <- print <$> readConfig c
printAction
但你真正想要的是绑定:
print =<< readConfig c
我不明白为什么会这样:
module Main where
import Control.Monad.Reader
data Config = Config Int
getA :: (Monad m) => ReaderT Config m Int
getA = do
Config a <- ask
return a
readConfig :: Config -> IO Int
readConfig = runReaderT getA
main :: IO ()
main = do
print "Start"
let a = Config 2
b <- readConfig a -- Will be printed
print b
let c = Config 4
print <$> readConfig c -- Silence, nobody complains..
print "Done"
结果是:
"Start"
2
"Done"
为什么 print <$> readConfig a
是空的?即使 -Wall
也没有人抱怨这个...
(我在 godbolt 中尝试了 diff ghc 版本,但结果保持不变)
编辑: 好的,我找到了问题的等效描述,感谢@chi和@David:
module Main where
test :: IO ()
test = do
print "test"
return ()
main :: IO ()
main = do
let t = test -- equivalent to print <$> readConfig c, is IO (IO ())
test -- equivalent to print b is IO ()
现在,我只想知道为什么 let t
不评估。根据我的直觉,以前很明显,但现在不明显了......但是有答案(esp. from Tanner Swett)
GHC 8.10.3 确实用 -Wall 抱怨这个(在我将你的代码中的 initConfig
更改为 readConfig
之后):
A do-notation statement discarded a result of type ‘IO ()’
Suppress this warning by saying ‘_ <- print <$> readConfig c’
您有 readConfig c
类型 IO Int
。然后你 fmap print
,给出类型为 IO (IO ())
的东西。由于结果未绑定到 do 块中的变量,因此将其丢弃。
在 fmap 的类型 Functor f => (a -> b) -> f a -> f b
中,我们有 f
是 IO
,a
是 Int
,b
是 IO ()
.所以它与 (Int -> IO ()) -> IO Int -> IO (IO ())
.
这可行:
printAction <- print <$> readConfig c
printAction
但你真正想要的是绑定:
print =<< readConfig c