CPS (Continuation Passing Style)

CPS(延续传递风格)是指函数不把处理结果作为返回值返回而是把处理结果传递给下一个函数的编码风格。

与此相对,函数把处理结果作为返回值返回的编码风格被称为直接编码风格。

add :: Int -> Int -> Int
add x y = x + y square :: Int -> Int
square x = x * x pythagoras :: Int -> Int -> Int
pythagoras x y = add (square x) (square y) add_cps :: Int -> Int -> ((Int -> r) -> r)
add_cps x y = \k -> k (add x y) square_cps :: Int -> ((Int -> r) -> r)
square_cps x = \k -> k (square x) pythagoras_cps :: Int -> Int -> ((Int -> r) -> r)
pythagoras_cps x y = \k ->
square_cps x $ \x_squared ->
square_cps y $ \y_squared ->
add_cps x_squared y_squared $ k chainCPS :: ((a -> r) -> r) -> (a -> ((b -> r) -> r)) -> ((b -> r) -> r)
chainCPS s f = \k -> s $ \x -> f x $ k pythagoras_cps' :: Int -> Int -> ((Int -> r) -> r)
pythagoras_cps' x y =
square_cps x `chainCPS` \x_squared ->
square_cps y `chainCPS` \y_squared ->
add_cps x_squared y_squared main = do
print $ pythagoras 3 4
pythagoras_cps 3 4 print
pythagoras_cps' 3 4 print {-
25
25
25
-}

这里 add, square, pythagoras 函数把处理结果直接返回,是直接编码风格。

而 add_cps, square_cps, pythagoras_cps 函数把处理结果传递给下一个函数,是CPS编码风格。

chainCPS 函数实现了一个通用的CPS风格函数,它能将CPS编码风格的函数串联起来。

Samples

module Continuation where

idCPS :: a -> (a -> r) -> r
idCPS a ret = ret a mysqrt :: Floating a => a -> a
mysqrt x = sqrt x test1 :: IO ()
test1 = print (mysqrt 4) mysqrtCPS :: Floating a => a -> (a -> r) -> r
mysqrtCPS a k = k (sqrt a) test2 :: IO ()
test2 = mysqrtCPS 4 print test3 :: Floating a => a
test3 = mysqrt 4 + 2 test4 :: Floating a => a
test4= mysqrtCPS 4 (+ 2) fac :: Integral a => a -> a
fac 0 = 1
fac n = n * fac (n - 1) test5 :: Integral a => a
test5 = fac 4 + 2 facCPS :: Integral a => a -> (a -> r) -> r
facCPS 0 k = k 1
facCPS n k = facCPS (n - 1) $ \ret -> k (n * ret) test6 :: Integral a => a
test6 = facCPS 4 (+ 2) test7 :: IO ()
test7 = facCPS 4 print newSentence :: Char -> Bool
newSentence = flip elem ".?!" newSentenceCPS :: Char -> (Bool -> r) -> r
newSentenceCPS c k = k (elem c ".?!") mylength :: [a] -> Integer
mylength [] = 0
mylength (_ : as) = succ (mylength as) mylengthCPS :: [a] -> (Integer -> r) -> r
mylengthCPS [] k = k 0
mylengthCPS (_ : as) k = mylengthCPS as (k . succ) test8 :: Integer
test8 = mylengthCPS [1..2006] id test9 :: IO ()
test9 = mylengthCPS [1..2006] print main = do
test1
test2
print test3
print test4
print test5
print test6
test7
print test8
test9 {-
2.0
2.0
4.0
4.0
26
26
24
2006
2006
-}

Haskell语言学习笔记(29)CPS的更多相关文章

  1. Haskell语言学习笔记(88)语言扩展(1)

    ExistentialQuantification {-# LANGUAGE ExistentialQuantification #-} 存在类型专用的语言扩展 Haskell语言学习笔记(73)Ex ...

  2. Haskell语言学习笔记(79)lambda演算

    lambda演算 根据维基百科,lambda演算(英语:lambda calculus,λ-calculus)是一套从数学逻辑中发展,以变量绑定和替换的规则,来研究函数如何抽象化定义.函数如何被应用以 ...

  3. Haskell语言学习笔记(69)Yesod

    Yesod Yesod 是一个使用 Haskell 语言的 Web 框架. 安装 Yesod 首先更新 Haskell Platform 到最新版 (Yesod 依赖的库非常多,版本不一致的话很容易安 ...

  4. Haskell语言学习笔记(20)IORef, STRef

    IORef 一个在IO monad中使用变量的类型. 函数 参数 功能 newIORef 值 新建带初值的引用 readIORef 引用 读取引用的值 writeIORef 引用和值 设置引用的值 m ...

  5. Haskell语言学习笔记(39)Category

    Category class Category cat where id :: cat a a (.) :: cat b c -> cat a b -> cat a c instance ...

  6. Haskell语言学习笔记(72)Free Monad

    安装 free 包 $ cabal install free Installed free-5.0.2 Free Monad data Free f a = Pure a | Free (f (Fre ...

  7. Haskell语言学习笔记(44)Lens(2)

    自定义 Lens 和 Isos -- Some of the examples in this chapter require a few GHC extensions: -- TemplateHas ...

  8. Haskell语言学习笔记(38)Lens(1)

    Lens Lens是一个接近语言级别的库,使用它可以方便的读取,设置,修改一个大的数据结构中某一部分的值. view, over, set Prelude> :m +Control.Lens P ...

  9. Haskell语言学习笔记(30)MonadCont, Cont, ContT

    MonadCont 类型类 class Monad m => MonadCont m where callCC :: ((a -> m b) -> m a) -> m a in ...

随机推荐

  1. java中<load-on-startup>含义

    java中 load-on-startup 含义 java中的 load-on-startup 用于表示该servlet是否在servlet容器启动的时候加载. 示例: <load-on-sta ...

  2. vue-cli 下的 webpack 优化

    app bundle 可以通过组件懒加载优化 vender 优化方法: 使用 cdn,然后在 webpack 配置中指定 externals. 利用 webpack 的插件 DllPlugin 和 D ...

  3. java编译需要文件后缀名.java 而运行不需要后缀名.class

    对于java源文件HelloWorld.java编译命令:javac HelloWorld.java运行命令:java HelloWorld 编译需要文件后缀名.java 而运行不需要后缀名.clas ...

  4. win7 配置微软的深度学习caffe

    win7 配置微软的深度学习caffe   官方下载: https://github.com/Microsoft/caffe 然后 直接修改caffe目录下的windows目录下的项目的props文件 ...

  5. BaseAction编写:免去一些重复的代码,比如继承ActionSupport和实现ModelDriven接口

    1.BaseAction package com.learning.crm.base; import java.lang.reflect.ParameterizedType; import java. ...

  6. centos6+nginx+php+mysql+memcached+wordpress

    centos6+nginx+php+mysql+memcached+wordpress 搭建步骤(1) LNMP 平台搭建: 请参考:http://www.cnblogs.com/ligao/p/61 ...

  7. bzoj 4961: 除除除

    Description 我们定义一种操作是将一个正整数n(n>1)用某个整数d替换,这个数必须是n的约数(1≤d≤n).给你一个正整数n, 你需要确定操作进行的期望次数,如果我们希望不断地使用这 ...

  8. Spring 注解方式 实现 IOC 和 DI

    注:以下所有测试案例(最后一个除外)的测试代码都是同一个: package cn.tedu.test; import org.junit.Test; import org.springframewor ...

  9. JedisCluster中应用的Apache Commons Pool对象池技术

    对象池技术在服务器开发上应用广泛.在各种对象池的实现中,尤其以数据库的连接池最为明显,可以说是每个服务器必须实现的部分.   apache common pool 官方文档可以参考:https://c ...

  10. Java 运算符-=,+=混合计算详解

    +=与-=运算符混合计算解析: int x = 3; x += x -= x -= x += x -= x; 详解:算数运算按运算符优先级运算,从右至左计算. 1. x=x-x; 实际为 3 - 3 ...