首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Haskell和lazy Monads评估

Haskell和lazy Monads评估
EN

Stack Overflow用户
提问于 2011-10-17 20:49:44
回答 2查看 1.3K关注 0票数 8

在玩monads时,我经常遇到评估问题。现在,我理解了惰性计算的基本概念,但我不明白在Haskell中是如何懒惰地计算monads的。

考虑以下代码

代码语言:javascript
复制
module Main where
import Control.Monad
import Control.Applicative
import System

main = print <$> head <$> getArgs

在我看来,main函数应该打印第一个控制台参数,但它没有。

我知道

代码语言:javascript
复制
getArgs :: IO [String]
head <$> getArgs :: IO String
print <$> (head <$> getArgs) :: IO (IO ())
main :: IO (IO ())

显然,第一个参数没有打印在stdout上,因为第一个monad IO的内容没有求值。因此,如果我加入这两个monads,它就可以工作。

代码语言:javascript
复制
main = join $ print <$> head <$> getArgs

有没有人能帮我澄清一下?(或者给我一个指针)

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-10-17 21:04:37

Haskell 2010报告(语言定义) says

程序的值是模块Main中标识符main的值,对于某些类型的τ,它必须是IO τ类型的计算。当执行程序时,执行计算main,并丢弃其结果(类型为τ)。

您的main函数的类型为IO (IO ())。上面的引号表示只评估外部操作(IO (IO ())),并丢弃其结果(IO ())。你是怎么到这里来的?让我们来看看print <$>的类型

代码语言:javascript
复制
> :t (print <$>)
(print <$>) :: (Show a, Functor f) => f a -> f (IO ())

所以问题是你把fmapprint结合使用了。查看IOFunctor实例的定义

代码语言:javascript
复制
instance  Functor IO where
   fmap f x = x >>= (return . f)

您可以看到,这使得您的表达式等同于(head <$> getArgs >>= return . print)。要实现最初的目的,只需删除不必要的return

代码语言:javascript
复制
head <$> getArgs >>= print

或者,等效地:

代码语言:javascript
复制
print =<< head <$> getArgs

请注意,Haskell中的IO操作就像其他值一样-它们可以传递给函数或从函数返回,存储在列表和其他数据结构中,等等。IO操作不会计算,除非它是主计算的一部分。要将IO操作“粘合”在一起,请使用>>>>=,而不是fmap (它通常用于将纯函数映射到某些“框”中的值-在您的示例中是IO)。

还要注意,这与惰性计算无关,而是纯正的--从语义上讲,您的程序是一个纯函数,它返回一个IO a类型的值,然后由运行时系统解释。由于您内部的IO操作不是此计算的一部分,因此运行时系统将其丢弃。关于这些问题的一个很好的介绍是Simon Peyton Jones的"Tackling the Awkward Squad"的第二章。

票数 11
EN

Stack Overflow用户

发布于 2011-10-17 21:05:44

你有head <$> getArgs :: IO Stringprint :: Show a => a -> IO (),即monad中的值和从普通值到monad的函数。用于组合这些内容的函数是一元绑定运算符(>>=) :: Monad m => m a -> (a -> m b) -> m b

所以你想要的是

代码语言:javascript
复制
main = head <$> getArgs >>= print

(<$>)又名fmap,它的类型是Functor f => (a -> b) -> f a -> f b,所以当你想将一个纯函数应用于monad中的某个值时,它很有用,这就是为什么它可以与head一起使用,但不能与print一起使用,因为print不是纯函数。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7793981

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档