小编The*_*kle的帖子

你如何在Haskell中表示图形?

使用代数数据类型表示haskell中的树或列表很容易.但是你会怎么用印刷术来表示图形呢?看来你需要有指针.我猜你可以有类似的东西

type Nodetag = String
type Neighbours = [Nodetag]
data Node a = Node a Nodetag Neighbours
Run Code Online (Sandbox Code Playgroud)

这是可行的.然而感觉有点脱钩; 结构中不同节点之间的链接并不真正"感觉"像列表中当前上一个和下一个元素之间的链接一样,或者树中节点的父节点和子节点之间的链接.我有一种预感,即在我定义的图形上进行代数操作会受到通过标签系统引入的间接级别的阻碍.

主要是这种怀疑的感觉和不雅的感觉使我提出这个问题.在Haskell中定义图形是否有更好/更优化的方式?或者我偶然发现了本质上坚硬/根本的东西?递归数据结构很好,但这似乎是另一回事.自引用数据结构,与树和列表的自引用方式不同.它就像列表和树在类型级别是自引用的,但是图形在值级别是自引用的.

那真正发生了什么?

haskell types functional-programming graph algebraic-data-types

118
推荐指数
7
解决办法
3万
查看次数

左右折叠无限列表

我有以下段落的问题来自Learn You A Haskell(伟大的书imo,而不是贬低它):

一个很大的区别是右侧折叠在无限列表上工作,而左侧折叠不起作用!说白了,如果你在某个点拿一个无限列表并从右边折叠起来,你最终会到达列表的开头.但是,如果你在一个点上获得一个无限的列表,并且你试图从左边折叠起来,那么你永远不会达到目的!

我只是不明白这一点.如果你拿一个无限的列表并试图从右边折叠起来那么你将不得不从无穷远点开始,这就是没有发生(如果有人知道你能做到这一点的语言,请告诉:p ).至少,你必须根据Haskell的实现开始那里,因为在Haskell中,foldr和foldl不会采用一个参数来确定列表中应该开始折叠的位置.

我同意引用iff foldr和foldl接受确定列表中应该开始折叠的位置的参数,因为有意义的是,如果你采用无限列表并从定义的索引开始向右折叠它最终终止,而它不会无论你从哪里开始左折; 你将向无限折叠.但是,foldr和foldl 接受这个参数,因此引用没有意义.在Haskell中,无限列表上的左侧折叠和右侧折叠都不会终止.

我的理解是正确的还是我错过了什么?

haskell functional-programming list infinite fold

70
推荐指数
3
解决办法
7390
查看次数

OOP接口和FP类型类之间的区别

可能重复:
Java的接口和Haskell的类型类:差异和相似之处?

当我开始学习Haskell时,我被告知类型类与接口不同且功能更强大.

一年后,我广泛使用了接口和类型,我还没有看到它们如何不同的示例或解释.这不是一种自然而然的启示,或者我错过了一些明显的东西,或者实际上没有真正的区别.

搜索互联网并没有发现任何实质性内容.那么,你有答案吗?

oop haskell functional-programming interface typeclass

59
推荐指数
2
解决办法
7983
查看次数

函数不仅具有类型:它们是类型.和种类.并排序.帮助把一个强大的思想重新组合在一起

我正常做着"读睡前LYAH的一章"的例行公事,感觉我的大脑正随着每个代码样本而扩展.在这一点上,我确信我理解了Haskell的核心功能,现在只需要理解标准库和类型类,这样我就可以开始编写真正的软件了.

所以我正在阅读有关应用函子的章节,突然之间,本书声称函数不仅仅有类型,它们类型,并且可以这样处理(例如,通过使它们成为类型类的实例).( - >)是一个类似于任何其他类型的构造函数.

我的思绪又被吹了,我立刻跳下床,启动计算机,去了GHCi并发现了以下内容:

Prelude> :k (->)
(->) :: ?? -> ? -> *
Run Code Online (Sandbox Code Playgroud)
  • 究竟是什么意思?
  • 如果( - >)是一个类型构造函数,那么值构造函数是什么?我可以猜一猜,但不知道如何用传统data (->) ... = ... | ... | ...格式定义它.使用任何其他类型的构造函数都可以轻松完成:data Either a b = Left a | Right b.我怀疑我无法以这种形式表达它与极端奇怪的类型签名有关.
  • 我偶然发现了什么?较高的kinded类型有类似的签名* -> * -> *.想一想......( - >)也会出现在亲切的签名中!这是否意味着它不仅是一个类型构造函数,而且还是一种类型的构造函数?这与类型签名中的问号有关吗?

我已经阅读了某个地方(希望我能再次找到它,谷歌让我失望)关于能够通过从值,值类型,到各种类型,各种类型,到其他各种类型,任意扩展类型系统,到别的东西,等等永远.这是否反映在( - >)的签名中?因为我也遇到了Lambda多维数据集的概念和构造的微积分而没有花时间去真正研究它们,如果我没记错,可以定义采用类型和返回类型的函数,取值和返回值,获取类型和返回值,并获取返回类型的值.

如果我不得不猜测一个带有值并返回一个类型的函数的类型签名,我可能会这样表达:

a -> ?
Run Code Online (Sandbox Code Playgroud)

或者可能

a -> *
Run Code Online (Sandbox Code Playgroud)

虽然我没有看到根本不可变的原因,为什么第二个例子不能轻易地被解释为从类型a的值到类型*的值的函数,其中*只是字符串或类似的类型同义词.

第一个例子更好地表达了一个函数,它的类型在我的脑海中超越了一个类型签名:"一个函数,它接受一个类型为a的值并返回一些不能表示为类型的东西."

haskell types type-systems ghc higher-kinded-types

43
推荐指数
2
解决办法
2078
查看次数

Haskell元组构造函数(GHC)和语言及其实现之间的分离

当我意识到这一点时,哈斯克尔再次震惊了我的思绪

(x,y)
Run Code Online (Sandbox Code Playgroud)

只是语法糖

(,) x y
Run Code Online (Sandbox Code Playgroud)

当然我想把它扩展到更大的元组.但

(,) x ((,) y z)
Run Code Online (Sandbox Code Playgroud)

给我

(x,(y,z))
Run Code Online (Sandbox Code Playgroud)

这不是我想要的.一时兴起,我试过了

(,,) x y z
Run Code Online (Sandbox Code Playgroud)

它有效,给出我想要的东西:

(x,y,z)
Run Code Online (Sandbox Code Playgroud)

这提出了一个问题:你能走多远?令我惊讶的是,似乎没有任何限制.以下所有都是有效的运营商:

(,)
(,,)
(,,,)
(,,,,)
--etc
(,,,,,,,,,,,,,,)
(,,,,,,,,,,,,,,,)
--etc
(,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,)
--etc
Run Code Online (Sandbox Code Playgroud)

这种行为是惊人的,并导致我的实际问题:它是否可以在我自己的功能中模拟?或者它只是元组运算符的GHC特定功能?我认为它是后者,因为我已经阅读了haskell98规范和iirc它说实现只需要为最多15个项目定义元组运算符.而GHC已经全力以赴,让你可以达到任意限制.

那么,是否可以在haskell实现本身中定义这个运算符/函数族,只使用类型系统和现有语言特性(声明,类型签名,函数定义等)?如果是这样,怎么样?或者这是不可能的,你必须考虑编译器来找到这个函数集合的支持框架?

这导致了一个更普遍的问题:Haskell本身支持多少Haskell,通过类型和函数定义,声明等; 以及编译器/实现支持多少?(我知道GHC是用Haskell编写的,但没有回答这个问题)

也就是说,如果你放弃标准库(包括前奏)并在原始的Haskell中从头开始做所有事情; 是否可以使用GHC的所有功能构建一个完整的实现,只使用最少的一组功能?为了使用Haskell构建haskell实现,您需要哪些最小的语言功能集?我是否可以放弃前奏,然后在GHC内手动完全重建?如果你放弃了前奏而从不导入任何东西,你还有什么可以继续使用?

看起来好像我问了一百万个问题,但他们真的都试图用不同的措辞问同样的问题.给你最好的拍摄!

haskell functional-programming tuples comma ghc

35
推荐指数
1
解决办法
5025
查看次数

同性恋和"不受限制"的自我修改代码+ lisp是否真的可以自我修改?

我将继续承认我对Lisp的了解非常少.但是我对这门语言非常感兴趣,并计划在不久的将来开始认真学习它.我对这些问题的理解无疑是有缺陷的,所以如果我说出任何错误的内容,请评论并纠正我而不是贬低.

真正的同性恋和自我修改的语言

我正在寻找支持Homoiconicity(代码与数据表示相同)和不受限制的自我修改的编程语言示例(Unrestricted意味着您可以更改正在运行的代码的每个方面,而不仅仅是发出新代码或更改函数指针/代表).

到目前为止我发现的三个例子符合这个标准:

  1. 机器代码.Homoiconic在一切都是一个数字.无限制地可修改,因为它包含指针,可用于操纵任何内存地址,无论该地址是保存代码还是数据.
  2. Malbolge.与机器代码相同的推理.每条指令在执行后都会自行修改
  3. 脱氧核糖核酸.不是编程语言,但仍然很有趣.它不是与机器代码一样的自我修改; 实际指令+数据在哪里修改到位.然而,它是自我复制的,并且可以根据它的先前状态进行变异/进化(具有副作用,例如辐射时不时地拧紧它).无论如何,这只是一种间接的自我修改方式.简而言之,DNA可以自我修饰,但它可以通过在相关突变中重现自身的真实性来实现.DNA的物理串是"不可变的".

为什么Lisp不在此列表中

Lisp不在那个列表中,因为在我看来,Lisp 几乎只是Homoiconic,并且只支持受限制的自我修改.你可以做点什么

(+ 1 2 3)
Run Code Online (Sandbox Code Playgroud)

这将做同样的事情

(eval '(+ 1 2 3))
Run Code Online (Sandbox Code Playgroud)

第一个版本(+ 1 2 3)是原始代码,而第二个版本是数据.通过假设这个陈述的真实性,可以说Lisp甚至不是杀人的.代码与数据具有相同的表示形式,即它们都是列表/树/ S表达式.但事实上你必须明确地标记这些列表/树/ S表达式中的哪些是代码以及哪些是我的数据似乎说Lisp毕竟不是杀人的.这些表示非常相似,但它们的细节不同,您必须实际说明您是在处理代码还是数据.这绝不是一件坏事(实际上其他任何东西都会是疯狂的),但它强调了Lisp和机器代码之间的区别.在机器代码中,您不必明确标记哪些数字是指令,哪些是指针,哪些是数据.在实际需要解释之前,一切都只是一个数字,此时它可以是任何一个.

对于不受限制的自我修改,这是一个更强大的案例.当然,您可以获取代表某些代码并对其进行操作的列表.例如改变

'(+ 1 2 3)
Run Code Online (Sandbox Code Playgroud)

'(+ 1 4 3)
Run Code Online (Sandbox Code Playgroud)

然后你运行它eval.但是当你这样做时,你只是编译一些代码并运行它.您没有修改现有代码,只是发出并运行新代码.C#可以使用表达式树完全相同的事情,即使是一种不太方便的格式(由于C#代码对其AST具有不同的表示而产生,而不是Lisp,这它自己的AST).您是否可以实际获取整个源文件并在运行时开始修改整个源文件,对源文件所做的更改会对程序行为产生实时影响?

除非有某种方法可以做到这一点,否则Lisp既不是讽刺也不是自我修改.(为了推断定义的争论,Lisp不是同源的,也不是自我修改到与机器代码相同的程度.)

如何制作Lisp Homoiconic/Unrestrictedly self-modifiable

我可以看到3种可能的方法使Lisp像机器代码一样可以单调/自我修改.

  1. 非Von-Neumann架构.如果有人能发明一些令人惊奇的假设机器,其中程序的最低级别表示是一个可以直接执行的AST(不需要进一步编译).在这样的机器上,AST将代表可执行指令以及数据.不幸的是,问题不会得到解决,因为AST仍然必须是代码或数据.eval函数的预设不会改变这一点.在机器代码中,您可以根据需要在代码和数据之间来回切换.而使用eval和Lisp,一旦你将某些列表从数据转换为代码并执行它,就无法再将该列表作为数据返回.实际上,该列表已经永远消失,并且已经被它的价值所取代.我们会遗漏一些至关重要的东西,这恰好是指针.
  2. 列出标签.如果要求每个列表也具有唯一标签,则可以通过针对具有给定标签的列表运行函数来进行间接自修改.结合延续,这最终将允许自动修改代码与机器代码具有相同的意义.标签与机器代码存储器地址等效.例如,考虑一个Lisp程序,其中AST的顶部节点具有标签"main".在main中,你可以执行一个函数,它接受一个标签,一个Integer,一个Atom,并将原子复制到List,其标签与提供给函数的标签相匹配,在Integer指定的索引处.然后在main上调用当前的continuation.你去,自我修改代码.
  3. Lisp Macros.我没有花时间去理解Lisp宏,他们实际上可能正是我正在考虑的事情.

点1.结合2.将产生一个完全自我修改的Lisp.前提是可以生产所描述的神奇的Lisp机器.2.单独可以产生自我修改的Lisp,但是在冯·诺依曼架构上的实现可能非常低效.

问题

  1. 机器码,dna和malbolge以外的任何语言都可以完全自我修改并且是同音的吗?
  2. (如果你做了tl,请不要打扰回答;上面的文字博士).lisp真的是homoiconic +自我修改吗?如果你这样说,你能准确引用我在论证中误入歧途的地方吗?

附录

语言具有不受限制的自我修改但不具有杀戮性

  1. 部件.代码使用单词而不是数字,因此失去了homiconicity,但它仍然有指针,它保留对内存的完全控制并允许不受限制的自我修改.
  2. 任何使用原始指针的语言.例如C/C++/Objective C.与Assembly相同的参数
  3. 包含虚拟指针的JIT语言.例如,C#/ .net在不安全的上下文中运行.与Assembly相同的论点.

其他概念和语言可能在某种程度上相关/有趣:Lisp,Ruby,Snobol,Forth和它的编译时元编程,Smalltalk和它的反射,无类型的lambda演算,它的属性是一切都是函数(哪种意味着假设我们可以发明一台直接执行lambda演算的机器,lambda演算将是homoiconic而Von Neumann机器代码在所述机器上运行时不会.[并且Godels定理将是可执行的.哈哈,可怕的想法:P])

lisp assembly machine-code self-modifying homoiconicity

29
推荐指数
2
解决办法
5237
查看次数

为什么这个函数的类型(a - > a) - > a?

为什么这个函数的类型(a - > a) - > a?

Prelude> let y f = f (y f)
Prelude> :t y
y :: (t -> t) -> t
Run Code Online (Sandbox Code Playgroud)

它不应该是无限/递归类型吗?我打算尝试将我认为类型应该是的,但我出于某种原因无法做到这一点.

y :: (t -> t) -> ?WTFIsGoingOnOnTheRHS?
Run Code Online (Sandbox Code Playgroud)

我不知道f(yf)如何解析为一个值.以下对我来说更有意义:

Prelude> let y f x = f (y f) x
Prelude> :t y
y :: ((a -> b) -> a -> b) -> a -> b
Run Code Online (Sandbox Code Playgroud)

但它仍然令人难以置信的混乱.这是怎么回事?

recursion haskell types anonymous y-combinator

21
推荐指数
4
解决办法
792
查看次数

Self和Smalltalk之间的差异

我只是在寻找将Self与Smalltalk区分开来的原因.

这不应该是大猩猩与鲨鱼的问题.我不是在找一个更好的理由,我只是把一个定义为与另一个不同的东西感到困惑.在阅读了大约2个小时后,它们对我来说似乎都是同一种语言,并且用一些代码捣乱(旁白:我终于理解了Smalltalk版本的"Everything is a object".我必须说,它真是太棒了.哈哈!我认为C#已经钉了......但它甚至没有接近这个!XD)

我在某个地方读过的随机内容,过去几年的某个时间:

  • Smalltalk赋值和消息/消息传递是唯一不是对象的东西,但是在Self中,即使这些东西在对象框架中也占有一席之地
  • "自我甚至比Smalltalk更加纯粹的OO".我无法找到更具体的阐述.

oop paradigms smalltalk selflanguage

17
推荐指数
2
解决办法
1694
查看次数

显示两种不同的斐波那契函数是等价的

我正在努力学习如何正确地证明程序的正确性.我从头开始,在第一步/主题介绍中挂断了.

本文关于全函数规划的文章中,给出了斐波那契函数的两个定义.传统的一个:

fib 0 = 0
fib 1 = 1
fib n = fib (n-1) + fib (n-2)
--fib (n+2) = fib (n+1) + fib (n+2) --The definition as given in the paper 
                                    --It seems incorrect to me. Typo?
Run Code Online (Sandbox Code Playgroud)

和我以前从未见过的尾递归版本:

fib' n = f n 0 1
f 0 a b = a
f n a b = f (n-1) b (a+b)
Run Code Online (Sandbox Code Playgroud)

该论文随后声称,通过归纳证明两个函数对所有正整数n都返回相同的结果是"直截了当"的.这是我第一次想到分析这样的程序.认为你可以证明两个程序是等价的,这是非常有趣的,所以我立即尝试通过归纳自己来做这个证明.要么我的数学技能都生锈了,要么任务实际上并不那么简单.

我证明了n = 1

fib' 1 = f 1 0 1
       = f 0 1 1 …
Run Code Online (Sandbox Code Playgroud)

haskell correctness functional-programming fibonacci induction

15
推荐指数
4
解决办法
1246
查看次数

浏览前奏的源代码会带来奇怪的现象

我正在寻找定义,seq并遇到了这种奇怪.为什么所有这些函数都有相同/相似的定义?

seq :: a -> b -> b
seq = let x = x in x

inline :: a -> a
inline = let x = x in x    

lazy :: a -> a
lazy = let x = x in x
Run Code Online (Sandbox Code Playgroud)

源代码中有更多此定义.这是怎么回事?

haskell standard-library ghc

15
推荐指数
2
解决办法
475
查看次数