Haskell do notation

栏目: 编程语言 · 发布时间: 7年前

内容简介:从普通的语言切换过来的时候,看到return总是让人费解。因为Haskell中的return 根本就不是普通语言中的return。这篇文章是看完Haskell Wiki [#]_ 以后写的一 篇笔记,当然主要是自己的理解,下面的代码部分来自wiki,部分属于自己捏造。通常我们学习Haskell都是看.. code:: haskell

从普通的语言切换过来的时候,看到return总是让人费解。因为Haskell中的return 根本就不是普通语言中的return。这篇文章是看完Haskell Wiki [#]_ 以后写的一 篇笔记,当然主要是自己的理解,下面的代码部分来自wiki,部分属于自己捏造。

do-notation

通常我们学习Haskell都是看 Learn You a Haskell for Great Good [#]_ 。这篇 教程在第12章第一次引入了Haskell的do-notation,他说,有这样一个函数:

.. code:: haskell

foo :: Maybe String
foo = Just 3   >>= (\x ->
    Just "!" >>= (\y ->
    Just (show x ++ y)))

我们可以用do-notation写成下面这样以减少lambda函数的使用:

.. code:: haskell

foo :: Maybe String
foo = do
    x <- Just 3
    y <- Just "!"
    Just (show x ++ y)

Haskell Report 2010 [#]_ 上是这么说的: "A do expression provides a more conventional syntax for monadic programming." do作为一种语法糖,让 Haskell写起来更方便。

>> operator ~~~~~~~~~~~~~~~~~~~

为了完全理解do,我们首先要把它变回去。举个例子:

.. code:: haskell

manyPutStrs = do
    putStr "Hello"
    putStr " "
    putStr "world!"
    putStr "\n"

其类型为 manyPutStrs :: IO () 。它其实相当于:

.. code:: haskell

manyPutStrs = putStr "Hello" >> putStr " " >> putStr "world!" >> putStr "\n"

我们知道 >> 的类型为: (>>) :: Monad m => m a -> m b -> m b ,即, 执行 m a ,但是丢弃其结果,并且执行 m b ,最终结果的类型就是 m b 的类型。 manyPutStrs 的类型就是 m b 也就是:

.. code:: bash

Prelude> :t putStr "!"
putStr "!" :: IO ()

>>= operator ~~~~~~~~~~~~~~~~~~

只进行输出的程序好像没有太大的用处,那么我们来举个能够和用户交互的例子:

.. code:: haskell

helloBody = do
    putStrLn "what's your name?"
    name <- getLine
    putStrLn $ "Hello " ++ name

首先我们来看一下这个函数的类型:

.. code:: bash

Prelude> :l fun.hs
[1 of 1] Compiling Main             ( fun.hs, interpreted )
Ok, modules loaded: Main.
Main> :t helloBody
helloBody :: IO ()
Main> helloBody
what's your name?
jhon
Hello jhon

这个函数的最终类型为 helloBody :: IO () 的原因也是因为最后一条语句的类型 为 putStrLn "hello" :: IO () 。但是对于 name <- getLine 好像并不是 和上面的那个例子那样简单,首先来看一下 getLine 的类型:

.. code:: bash

Prelude> :t getLine
getLine :: IO String

<- 的作用就是把 StringIO String 中取出来并且给 name 绑上。 而且 name 在后面还用上了。其实上面的函数就相当于:

.. code:: haskell

helloBody'' = putStrLn "what's your name?" >>
            getLine >>= (\name ->
                         putStrLn $ "Hello " ++ name
                        )

来看看他的类型和效果是否一样:

.. code:: bash

Prelude> :l fun.hs
[1 of 1] Compiling Main             ( fun.hs, interpreted )
Ok, modules loaded: Main.
Main> :t helloBody''
helloBody'' :: IO ()
Main> helloBody''
what's your name?
jhon
Hello jhon

其中 >>= 的类型为 (>>=) :: Monad m => m a -> (a -> m b) -> m b 。理解 了这个操作符理解上面的代码也就没问题了。

return

首先来看一下 return 的类型: return :: Monad m => a -> m a 其实在Haskell 中,return的作用就是将数据塞到一个盒子里,这里所说的盒子也就是我们的Monad。 我们来举个例子:

.. code:: haskell

foo = do
    return "hi"
    putStrLn "foo"

foo的类型为 foo :: IO () ,这是因为如上面我们所说的,这相当于::

foo = return "hi" >> putStrLn "foo"

.. [#] https://en.wikibooks.org/wiki/Haskell/do_notation .. [#] http://learnyouahaskell.com/chapters .. [#] https://www.haskell.org/onlinereport/haskell2010/haskellch3.html#x8-470003.14


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

概率

概率

[俄]施利亚耶夫 / 周概容 / 高等教育出版社 / 2008-1 / 48.00元

《概率(第2卷)(修订和补充第3版)》是俄国著名数学家A.H.施利亚耶夫的力作。施利亚耶夫是现代概率论奠基人、前苏联科学院院士、著名数学家A.H.柯尔莫戈洛夫的学生,在概率统计界和金融数学界影响极大。《概率(第2卷)(修订和补充第3版)》作为莫斯科大学最为出色的概率教材之一。分为一、二两卷,并配有习题集。第二卷《概率(第2卷)(修订和补充第3版)》是离散时间随机过程(随机序列)的内容。重点讲述(强......一起来看看 《概率》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具