Haskell语言学习笔记(29)CPS
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的更多相关文章
- Haskell语言学习笔记(88)语言扩展(1)
ExistentialQuantification {-# LANGUAGE ExistentialQuantification #-} 存在类型专用的语言扩展 Haskell语言学习笔记(73)Ex ...
- Haskell语言学习笔记(79)lambda演算
lambda演算 根据维基百科,lambda演算(英语:lambda calculus,λ-calculus)是一套从数学逻辑中发展,以变量绑定和替换的规则,来研究函数如何抽象化定义.函数如何被应用以 ...
- Haskell语言学习笔记(69)Yesod
Yesod Yesod 是一个使用 Haskell 语言的 Web 框架. 安装 Yesod 首先更新 Haskell Platform 到最新版 (Yesod 依赖的库非常多,版本不一致的话很容易安 ...
- Haskell语言学习笔记(20)IORef, STRef
IORef 一个在IO monad中使用变量的类型. 函数 参数 功能 newIORef 值 新建带初值的引用 readIORef 引用 读取引用的值 writeIORef 引用和值 设置引用的值 m ...
- Haskell语言学习笔记(39)Category
Category class Category cat where id :: cat a a (.) :: cat b c -> cat a b -> cat a c instance ...
- Haskell语言学习笔记(72)Free Monad
安装 free 包 $ cabal install free Installed free-5.0.2 Free Monad data Free f a = Pure a | Free (f (Fre ...
- Haskell语言学习笔记(44)Lens(2)
自定义 Lens 和 Isos -- Some of the examples in this chapter require a few GHC extensions: -- TemplateHas ...
- Haskell语言学习笔记(38)Lens(1)
Lens Lens是一个接近语言级别的库,使用它可以方便的读取,设置,修改一个大的数据结构中某一部分的值. view, over, set Prelude> :m +Control.Lens P ...
- Haskell语言学习笔记(30)MonadCont, Cont, ContT
MonadCont 类型类 class Monad m => MonadCont m where callCC :: ((a -> m b) -> m a) -> m a in ...
随机推荐
- Qt下 QString转char*(转)
Qt下面,字符串都用QString,确实给开发者提供了方便,想想VC里面定义的各种变量类型,而且函数参数类型五花八门,经常需要今年新那个类型转换 Qt再使用第三方开源库时,由于库的类型基本上都是标准的 ...
- Java Web Service 学习笔记
一.服务端 1. 创建Java工程 2. 创建接口HostipalServiceInterface package ws_server; import javax.jws.WebMethod; imp ...
- JZ2440 裸机驱动 第12章 I2C接口
本章目标: 了解I2C总线协议: 掌握S3C2410/S3C2440中I2C接口的使用方法: 12.1 I2C总线协议及硬件介绍 12.1.1 I2C总线协议 1 I2C总线的概念 2 I2C总线的信 ...
- sysbench 0.5 基准测试
sysbench 介绍 SysBench是一个模块化的.跨平台.多线程基准测试工具,主要用于评估测试各种不同系统参数下的数据库负载情况.它主要包括以下几种方式的测试: cpu性能 磁盘io性能 调度程 ...
- python3 urllib
1.获取页面内容 第一种方式: import urllib.request url = 'https://www.baidu.com/' r = urllib.request.urlopen(url) ...
- Javascript中的delete介绍
关于JavaScript中的Delete一直没有弄的很清楚,最近看到两篇这方面的文章,现对两文中部分内容进行翻译(内容有修改和添加,顺序不完全一致,有兴趣推荐看原文),希望能对大家有所帮助 一.问题的 ...
- spring Annotation based configuration
spring 注解相关 https://docs.spring.io/spring/docs/3.0.0.M3/reference/html/ch04s11.html
- 峰Spring4学习(1)HelloWorld
HelloWorld.java: package com.cy.test; public class HelloWorld { public void say(){ System.out.printl ...
- 通过优化在UE4中实现良好性能和高质量视觉效果
转自:http://gad.qq.com/program/translateview/7160166 译者:赵菁菁(轩语轩缘) 审校:李笑达(DDBC4747) 对于任何追求UE4性能最佳.同时又想 ...
- Nexus3 仓库搭建(基于Docker)
Nexus Repository OSS 支持的仓库类型 安装方法(使用docker) 命令: sudo docker run -d \ --name nexus3 \ --restart=alway ...