![](https://img-blog.csdnimg.cn/20201014180756724.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
函数式编程和Haskell
文章平均质量分 65
这个专栏中所有东西都是写给自己看的,只是作为学习中的一个补充笔记,且大部分篇章是草稿。不保证系统性,不保证正确性,只作为一个存档。如果对您有参考价值的话,很荣幸能帮到您!
转载请注明出处。
WinterShiver
自然语言处理博士生,熟悉Python/Haskell
CSDN放的东西都是草稿,很多东西可能是是粗浅乃至错误的,欢迎讨论
展开
-
Python:迭代器和生成器的编程模型 - 以阴阳谜题为例
笨比试图理解Scheme实现的阴阳谜题未果,先针对比较简单的Python展开理解🥺本文介绍了理解Python求解阴阳谜题的语法基础,然后讲解了Python求解阴阳谜题的代码,包括详细的执行过程。原创 2023-02-28 20:38:42 · 176 阅读 · 0 评论 -
Python:基于生成器和filter实现惰性求值 - 以筛法质数计算为例
函数式编程值得称道的是惰性计算概念的引入,以Haskell实现埃氏筛法计算质数的代码作为代表。在Python中通过生成器实现类似的功能。原创 2023-03-06 10:41:26 · 163 阅读 · 0 评论 -
Haskell:Data Functor和Control Functor
从范畴论的角度来看,Control functors are the enriched functors of the category of linear functions, while data functors are the regular functors.从功能上,Data Functor只能做值的容器,Control Functor表示的是一个值在被执行副作用时的中间状态。Data Functor和Control Functor是两个不同的概念,只是在Haskell中有所混淆。原创 2022-10-12 16:07:23 · 117 阅读 · 0 评论 -
Haskell:嵌套函子,join,函子组合子
不难发现我们需要一个“嵌套函子”的类型。考虑到“两个函子结合之后依然是函子”,我们先看看用。事情来自于我的一个突发奇想,想要实现一个广义的。函数,实现处理嵌套Functor的效果,即实现。类型类,而不是定义新的类型类,能不能实现效果。所以我们的问题转化为,如何把类型如。不允许部分应用,所以是不能写出一个。的,即使新定义一个类型类也不行。另外一个思路是直接定义一个。的值相互转化,即如何把。原创 2022-09-19 15:47:33 · 203 阅读 · 0 评论 -
几种在lambda演算中编码自然数的方式
学习了A Tutorial Introduction to the Lambda Calculus, by Raul Rojas这篇lecture note,简单概括了一下文章内容。以及对Encoding Data in Lambda Calculus: An Introduction, by Frank (Peng) Fu的学习笔记原创 2022-06-05 12:17:56 · 412 阅读 · 0 评论 -
Scheme: Understanding Continuation-Passing-Style the Easiest Way, with the example of Fibonacci
; Fibonacci (define (fibo i) (if (= i 0) 1 (* i (fibo (- i 1))))); Rewrite in if-then-else form(define (ite i cond kSucc kFail) (if (cond i) (kSucc i) (kFail i)))(define (fiboIte i) (ite i (lambda (i) (= i 0))原创 2022-05-18 13:13:18 · 111 阅读 · 0 评论 -
Haskell: 求解24点问题的多种变体
24点问题给定一个长度为4的整数数组 cards ,代表你有 4 张卡片,每张卡片上都包含一个整数。您应该使用运算符 [’+’, ‘-’, ‘*’, ‘/’] 和括号 ‘(’ 和 ‘)’ 将这些卡片上的数字排列成数学表达式,以获得值 target。你须遵守以下规则:除法运算符 ‘/’ 表示有理数除法。例如, 4 /(1 - 2 / 3)= 4 /(1 / 3)= 12每个运算都在两个数字之间。特别是,不能使用 “-” 作为一元运算符。例如,如果 cards =[1,1,1,1] ,则表达式 “-1原创 2022-03-28 23:53:16 · 487 阅读 · 0 评论 -
Haskell:从二叉树中序遍历效率问题到foldr和CPS
问题问题:在O(n)时间对二叉树进行中序遍历考虑二叉树data Tree a = Null | Node (Tree a) a (Tree a)直观地写出中序遍历方法flatten :: Tree a -> [a]flatten Null = []flatten (Node l x r) = flatten l ++ [x] ++ flatten r我们分析flatten的时间复杂度,记二叉树包含节点个数的规模为n。因为(++)的时间复杂度取决于其第一个参数,即l ++ r的用时原创 2022-02-13 19:27:27 · 412 阅读 · 0 评论 -
Python函数式编程:谈谈global, nonlocal和闭包 - 以计数器为例
函数式编程原创 2022-01-16 00:41:54 · 459 阅读 · 0 评论 -
Haskell:type和kind杂记
type:函数和值等同视之,可将其视为某个type下的值,所以只需要关注他们的type。data constructor视为普通的函数,也只需要关注type。type family就是定义新的高阶type,比如type L Int = [Int],不能用这个语法,要用type family. type family也可以支持参数化类型,语法很灵活。kind:类型构造器、类型类,没有type有kind类型构造器如 (->) Maybe 等,基本是基本type的组合,比如*, * -> *原创 2021-12-22 08:02:39 · 344 阅读 · 0 评论 -
Haskell:如何类型化快速排序
以下为类型类版本的快排代码,type family版本待补。要点:用data+instance确定递推规则,从而定义递归函数。递推规则类似Haskell里的let in。用class+instance定义模式匹配。含有模式匹配的函数,需要先定义模式匹配,然后包装一层。{-# LANGUAGE MultiParamTypeClasses #-}-- {-# LANGUAGE TypeFamilies #-}-- {-# LANGUAGE GADTs #-}{-# LANGUAGE Func原创 2021-04-01 23:02:36 · 196 阅读 · 0 评论 -
Haskell日经
常见的吸引新人入坑的,短的但风格鲜明的代码import Data.List (partition)qSort :: Ord a => [a] -> [a]qSort [] = []qSort (x:xs) = qSort l ++ (x : qSort r) where (l, r) = partition (<x) xsprimes = 2 : filter isPrime [3..]isPrime n = null $ dropWhile原创 2020-12-12 23:10:27 · 82 阅读 · 0 评论 -
MacOS/Ubuntu/WindowsWSL配置Haskell环境
本文在Ubuntu安装Haskell环境管理工具stack和cabal,对其他Linux/Windows WSL也适用。安装并配置stack访问这里 https://docs.haskellstack.org/en/stable/README/#how-to-install 获得stack的安装方法curl -sSL https://get.haskellstack.org/ | sh执行这条指令安装stack,需要sudo安装好后测试chong@DESKTOP-6EQ6H57:~$ st.原创 2020-11-25 20:36:49 · 968 阅读 · 0 评论 -
Scheme中的call/cc
理解中断本部分是把 Continuation 在 JS 中的应用 这篇文章的例子用scheme重写了一遍,不用call/cc,只用church encoding实现中断。;; Functions of calculation: in a Church encoding manner;; for addF, the result of x+y is collected by F. The rest is the same.(define addF (lambda (x y F) (F原创 2020-10-11 14:54:34 · 385 阅读 · 0 评论 -
理解CPS中continuation passing的概念
本文原文地址前言接触CPS有一段时间了,知道CPS就是把值2写成\f -> f 2,传入的参数f是接下来要对值2进行的后续操作过程,所以把这里的f称为continuation。然而,我一直不知道这玩意为什么叫做continuation——我不知道这东西所指的“后续操作”是从哪里来的,不知道为什么计算要用这种方式延续。今天在学习The Little Schemer的时候终于找到了一个令我信服的应用场景,所以写篇博客说明一下这件事。这篇博客的问题来自Scheme,本来想用Python解释的,但是无奈原创 2020-09-04 22:17:47 · 337 阅读 · 0 评论 -
Haskell:通过class定义抽象数据类型
Haskell中定义数据类型基本都是使用data, type和newtype,其中data用来定义新类型。然而有些时候也可以且有必要用定义类型类(使用class关键字)的方式定义数据类型。比如定义一个抽象数据类型和代数结构对应,则这个代数结构就是集合+封闭运算,用class定义这个代数结构,可以保证实现的实例肯定定义了封闭运算。例如Semigroup里面的mappend,将特定类型实现为Semigroup需要实现mappend,从而保证在这个类型上定义的半群定义完整。...原创 2020-08-31 10:34:39 · 479 阅读 · 0 评论 -
和类型和积类型的CPS:以Haskell为例
给太长不看的人:字面量类型的CPS表示:从a变成(a -> r) -> r和类型的CPS表示:类型要求输入所有种类类型值的处理函数。例1:Maybe a变成r -> (a -> r) -> r或者(Unit -> r) -> (a -> r) -> r例2:Either a b变成(a -> r) -> (b -> r) -> r积类型的CPS表示:类型要求输入的处理函数处理类型值的全部信息。例1:(a, .原创 2020-08-21 00:10:13 · 402 阅读 · 0 评论 -
Haskell:理解Haskell中的CPS(Cont)
Haskell中的CPS在Control.Monad.Trans.Cont中定义,文档见于docs,源码见于code.源码重要的部分主要有三处:1. Cont的定义和一系列方法, 2. ContT Monad的定义,3. callCC的定义。下面分门别类来讲。CPS简单来说,CPS就是把x表示成\f -> f x,原本的h (g (f x))变成了x (f id),原本的f x y z变成了z . y . x $ f id。CPS的作用是在一些情况下表示数据结构(如和类型和积类型)或控制结构(如原创 2020-08-20 00:20:34 · 574 阅读 · 0 评论 -
Haskell:写一个漂亮的快排
写快速排序几乎是很多人被Haskell圈粉的第一瞬间,然而可能很多人一开始的实现并不是最优的。此处记录了我的心路历程。文章目录最初的实现使用filter只需要filter一次优雅地解决问题最初的实现quick_sort :: Ord a => [a] -> [a]quick_sort [] = []quick_sort [x] = [x]quick_sort xs = quick_sort [xs !! i | i <- [0..len-1], xs !! i <= .原创 2020-06-28 19:16:25 · 936 阅读 · 0 评论 -
Haskell:理解函数应用符和函数复合符,并应用($), (&), (.)减少嵌套调用中的括号嵌套
文章目录减少繁琐的括号嵌套函数应用符:($) and (&)函数复合符:(.)参考减少繁琐的括号嵌套Haskell中的求值顺序在1介绍。为了明确表示求值顺序,计算表达式中通常需要复杂的括号嵌套,比如((1+2)+(3*4)/(5/6))*(7+(8+9)-10)。但是,繁琐的括号嵌套有如下缺点:会引起视觉负担,在括号较为繁琐时并不能方便地看出表达式的求值顺序。繁琐的括号嵌套也和数学直觉相悖。在数学中,sin cos 1代表的就是sin(cos(1))的计算顺序。我们需要减少程序中的括号原创 2020-06-07 17:13:49 · 610 阅读 · 0 评论 -
Haskell: 表达式的计算顺序
文章目录Haskell的计算顺序特性Haskell的求值过程参考Haskell的计算顺序特性首先需要知道,Haskell使用first class function1,而且使用curried function.first class就是指这种元素可以传给子程序作为参数,可以从子程序里返回,可以赋给变量。Haskell里面的函数什么都能做,与数值无异。我们在下文中不区分“值”的概念,“值”既可以表示一个具体的数,布尔,也可以表示一个具体的函数。curried就是指函数只有一个参数,而返回其余的部分(原创 2020-06-07 16:49:39 · 581 阅读 · 0 评论 -
Haskell:在Monad中使用guard函数(守卫函数)
这篇文章讲的并不是guard语法,而是MonadPlus中的guard函数。一句话总结文章的内容:guard表达式在Monad环境中进行条件判断,起到filter的作用。MonadPlus和guardMonadPlus的定义:1. 在这里,我们只用到MonadPlus的幺半群和左零元性质,不涉及MonadPlus进一步发展中的一些问题2。首先,MonadPlus是Monad3,而幺半群性质即mzero和mplus构成MonadPlus集合上的幺半群。class (Monad m) => .原创 2020-06-07 11:23:17 · 693 阅读 · 0 评论 -
Haskell: 经典类型类FAM的重新设计
这篇文章是对张淞书相关部分的一个转述,仅作个人备忘使用。历史沿革Functor, Applicative, Monad, 最先提出来的是Functor,用来建模带box的数据。在这种情况下,下一个提出的是Monad,用来建模可能失败的计算(比如Maybe Monad),或者认为是合并箱子(依然比如Maybe Monad)。在这种情况下,发现Functor和Monad的粒度太粗了,于是引入了Applicative建模一种中间的情况,即函数和数据都带box的情况。张淞的书中提出Pointed,是因为p.原创 2020-06-06 21:49:12 · 181 阅读 · 0 评论 -
Haskell单一同态限定导致类型歧义:Ambiguous type variable ‘’ arising from a use of ‘’ prevents the constraint ‘’ f
为单一同态限定导致类型歧义提供一个例子。问题描述在下面这段代码中,在单一同态限定开启的状况下,函数的类型无法自动推导:my_liftA2 :: Applicative f => (c -> a -> b) -> f c -> f a -> f bmy_liftA2 f a b = f <$> a <*> b-- my_ap :: Applicative f => f (a -> b) -> f a -> f .原创 2020-06-04 01:27:10 · 384 阅读 · 0 评论 -
Haskell do notation 的正经定义
永远在用do,永远记不得do作为一个语法糖,对应的真实语法是什么。写一篇博文记一下。-- | ------------------------------------------------------ | (1) do { m1 } ==> m1-- | (2) do { m1; m2 } ==> m1 >> do { m2 }-- | (3) do { let s1; m1 s1 } ==> let s1 in do { m1 s1 }-- | (3’) do {原创 2020-06-01 23:39:10 · 674 阅读 · 0 评论 -
在Haskell中定义Y组合子
在Haskell中定义Y组合子这篇文章的创作动机是:看到了这个问题:Y Combinator in Haskell. 我之前遇到这个问题,没有思考过解决办法。而这个问题给出很多好的解决方法,于是对于其中具有代表性的方法进行了解读。本文分为四个部分:给出预备知识;定义问题;介绍解法;进行拓展。所有的lambda表达式都是用Haskell语法书写的。有些地方为了方便,表达式的书写风格不太好,但是保...原创 2020-05-01 00:03:36 · 435 阅读 · 0 评论 -
推导Y组合子
推导Y组合子这篇文章的创作动机是:之前一直不理解Y组合子是怎么被想出来的,查这方面的资料看到了重新发明 Y 组合子 JavaScript(ES6) 版,但是写得不太清楚,于是决定在本文彻底讲清楚。本文的主要内容是在递归函数的非递归定义中引入omega组合子和Y组合子,并推导他们的形式。本文分为三个部分:在FP中通常用递归的方式定义阶乘函数,本文首先对其给出了一个非递归的定义。对上述过程,...原创 2020-05-01 00:01:56 · 504 阅读 · 0 评论 -
关于无类型限制的lambda演算(Untyped Lambda Calculus)
关于无类型限制的lambda演算在阅读这篇博文之前,你最好已经阅读过A Tutorial Introduction to the Lambda Calculus (Raul Rojas)在接触Haskell几个月之后,才发觉Haskell不过是一个实现pattern match比较方便的工具,真正值得深入学习不仅有Haskell的实现和函数式编程的思想,还包括如下的内在理论知识:lambd......原创 2020-03-25 22:05:57 · 562 阅读 · 2 评论 -
Church Numeral: 品味和扩展
文章目录Church Numeral的定义品味:定义的合理性合理性1:同构合理性2:设计扩展:整数和有理数负数和减法除法参考Church Numeral的定义定义参考1zero s z = zincr n s z = n s (s z) -- = s (n s z)-- data ch = zero | incr zero-- type ch = (a -> a) ->...原创 2020-03-04 18:27:31 · 268 阅读 · 0 评论 -
Haskell: (-」) r Functor Applicative Monad 案例选讲
Haskell: (->) r Functor Applicative Monad 案例选讲(->) r 的 Functor Applicative Monad 方法实现类型构造器(->) r是Functor Applicative Monad的实例,相关定义如下:instance Functor ((->) r) where fmap = (.) (...原创 2020-02-06 22:39:26 · 214 阅读 · 0 评论 -
Haskell: 简单解析sequenceA
Haskell: 简单解析sequenceA文章目录Haskell: 简单解析sequenceAsequenceA的定义sequenceA的实用性sequenceA的意义参考sequenceA的定义-- sequenceA in PreludesequenceA :: (Applicative f, Traversable t) => t (f a) -> f (t a) ...原创 2020-02-01 21:13:00 · 279 阅读 · 0 评论 -
Haskell:二元函数求偏导数
Haskell:二元函数求偏导数问题对于已知的二元函数f = f(x, y),且有一个对一元函数求导的函数diff = diff(f)可用。问题:如何利用diff函数求f函数对于第一个、第二个参数的偏导数?解答首先确定上面提到函数的函数类型:f :: Double -> Double -> Doublediff :: (Double -> Double -> ...原创 2020-01-29 17:54:28 · 886 阅读 · 0 评论 -
Haskell:从Maybe Monad理解Monad
Haskell:从Maybe Monad理解Monad文章目录Haskell:从Maybe Monad理解MonadMonad的原始定义Maybe的Monad实现理解>>=总结Monad的原始定义-- Monad的原始定义class Monad m where return :: a -> m a (>>=) :: m a -> (a -...原创 2019-12-26 21:02:13 · 563 阅读 · 0 评论 -
Haskell:实现二叉树及其前序、中序、后序遍历和层序遍历
Haskell:实现二叉树及其前序、中序、后序遍历和层序遍历用函数式编程语言实现数据结构,是非常返璞归真的一件事情。我目前持续关注这一话题,将会在近期推出一部分关于Haskell实现各种数据结构的文章。-- BinaryTree.hs -- 定义类:二叉树-- 方法:主要是前序、中序、后序、层序遍历-- 心得:函数定义时老老实实用括号,不然会出问题;函数使用时可以用$符号-- fu...原创 2019-12-23 00:45:29 · 2129 阅读 · 2 评论 -
Haskell: 二叉树和Catalan数
Haskell: 二叉树和Catalan数文章目录Haskell: 二叉树和Catalan数理论Haskell实现:二叉树的定义Haskell实现:打印二叉树的信息Haskell实现:Catalan数的求解理论Catalan数:C(2n, n)=(2n)!/n!/n!关于n个节点二叉树种类数和Catalan数的关系,可阅读这篇博客。Haskell实现:二叉树的定义data Tree =...原创 2019-12-17 00:40:04 · 704 阅读 · 0 评论 -
Haskell:用foldr定义foldl
Haskell:用foldr定义foldl文章目录Haskell:用foldr定义foldl基础知识类型推导恒等证明Q&A总结基础知识fold操作是把一个列表聚合成一个值的过程,而在此基础上有foldl和foldr两种对称的实现。两个函数的一种定义如下:foldl :: Foldable t => (b -> a -> b) -> b -> t a -...原创 2019-11-29 11:56:32 · 947 阅读 · 0 评论 -
Haskell:写一个漂亮的归并排序
Haskell:写一个漂亮的归并排序引言依然是Haskell写漂亮系列,这次通过实现一个归并排序程序并改进,来体现函数式编程的魔力及编程技巧。第一版代码merge_sort :: Ord a => [a] -> [a]merge_sort [] = []merge_sort [x] = [x]merge_sort xs = merge_two (merge_sort le...原创 2019-11-24 15:49:36 · 840 阅读 · 0 评论 -
Python函数式编程: 求解24点
Python函数式编程: 求解24点引言本文实现三种大同小异的基于“遍历+递归”的搜索,从一个侧面体现了函数式编程的妙处。(所以,仅仅是简单的“遍历+递归”真的称得上是函数式编程么?捂脸笑)如果只想看24点的解法,直接看版本2.文章目录Python函数式编程: 求解24点引言求解思路基础:加减乘除、等于的定义版本0:阉割版,只能按照列表顺序加符号版本1:阉割版,只能串行版本2:正...原创 2019-11-22 19:49:34 · 566 阅读 · 0 评论 -
Python3中的函数式编程要素
Python3中的函数式编程要素学习python函数式编程时,学到的一些杂乱无章的要素。主要的范例来自最后的几篇参考,笔者基于参考材料构建例子,加入了相当多的笔者个人心得。文章目录Python3中的函数式编程要素用递归代替循环设计递归解决问题用列表推导式(列表解析)代替for循环基于列表推导式,设计递归解决问题用与或非逻辑代替流程控制if-elsewhile高阶函数高阶函数概论map re...原创 2019-11-21 14:30:43 · 428 阅读 · 0 评论 -
Haskell: 八皇后问题的求解和效率优化
Haskell: 求解八皇后问题无灵魂解法编程思路n皇后问题,在前m步保留已经放了m个之后的所有可能情况。在第m+1步再试图放1个上去,保留所有不产生冲突的情况,也就是已经放了m+1个之后的所有可能情况。以此类推,放满n个皇后为止。初步的实现和问题queen :: Int -> Int -> [[Int]]queen n 1 = [[i] | i <- [1..n]]...原创 2019-11-22 00:10:38 · 669 阅读 · 0 评论