Haskell do notation

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

内容简介:从普通的语言切换过来的时候,看到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


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

查看所有标签

猜你喜欢:

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

算法与数据结构(第二版)

算法与数据结构(第二版)

傅清祥、王晓东 / 电子工业出版社 / 2001-8-1 / 34.00

本书是《计算机学科教学计划1993》的配套教材之一。它覆盖了《计算机学科教学计划1993》中开列的关于算法与数据结构主科目的所有知识单元。其主要内容有:算法与数据结构的概念、抽象数据类型(ADT)、基于序列的ADT(如表,栈,队列和串等)。反映层次关系的ADT(如树,堆和各种平衡树等)、关于集合的ADT(如字典,优先队列和共查集等)、算法设计的策略与技巧、排序与选择算法、图的算法、问题的计算复杂性一起来看看 《算法与数据结构(第二版)》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具