我已经深入研究了haskell类型系统的细节,并试图找到类型类的优点.我已经学会了一堆,但我在以下几段代码上打了一堵墙.
使用这些类和实例定义:
class Show a => C a where
f :: Int -> a
instance C Integer where
f x = 1
instance C Char where
f x = if x < 10 then 'c' else 'd'
Run Code Online (Sandbox Code Playgroud)
为什么这会传递类型检查器:
g :: C a => a -> Int -> a
g x y = f y
yes :: C a => a -> Int -> String
yes x y = show (g x y)
Run Code Online (Sandbox Code Playgroud)
但这不是吗?
g :: C a => a -> …Run Code Online (Sandbox Code Playgroud) 我是Haskell的初学者,即使在阅读了foldr/foldl的几个解释之后,我也无法理解为什么我会在下面得到不同的结果.解释是什么?
Prelude> foldl (\_ -> (+1)) 0 [1,2,3]
4
Prelude> foldr (\_ -> (+1)) 0 [1,2,3]
3
Run Code Online (Sandbox Code Playgroud)
谢谢!
Haskell (as commonly implemented) does not have a call stack;
evaluation is based on graph reduction.
Run Code Online (Sandbox Code Playgroud)
真?这很有意思,因为虽然我自己从未体验过它,但我已经读过,如果你不使用折叠函数的严格版本然后强制评估无限折叠,你会得到堆栈溢出.当然,这表明存在堆栈.任何人都可以澄清吗?
直觉上,我希望"数学"答案all (==1) [1,1..]是True因为列表中只包含1的所有元素都等于1.但我理解"计算上",评估无限列表以检查事实上,每个元素实际上等于1将永远不会终止,因此表达式将"评估"到底部或?.
我发现这个结果反直觉而且有点令人不安.我认为列表无限的这个事实在数学上和计算上都会混淆这个问题,我很乐意听到在这个领域有一些见解和经验的人
我的问题是,哪个是数学上最正确的答案??还是True?关于为什么一个答案比另一个答案更正确的一些详细说明也将受到高度赞赏.
编辑:这可能间接地与库里 - 霍华德同构(程序是证明和类型是定理)和哥德尔的不完备性定理有关.如果我没记错的话,其中一个不完备性定理可以(非常粗略地)总结为"足够强大的形式系统(如数学或编程语言)无法证明所有可以在系统中表达的真实陈述"
math computer-science haskell data-structures infinite-recursion
这是我之前的问题的后续跟进.我不相信Lisp代码与Von Neumann架构上的机器代码一样是Homoiconic.对我来说似乎很明显,在这两种情况下代码都表示为数据,但似乎很明显,你可以在机器代码中比在Lisp中更自由地利用这个属性.
在使用机器代码时,自我修改代码非常容易,它总是偶然发生,通常是偶然的,并且(根据我的经验)是搞笑的结果.在编写一个简单的"打印数字0-15"程序时,我的一个指针可能会出现"off by one"错误.我最终会意外地将寄存器1中的任何内容转储到包含下一条指令的内存中的地址中,而是执行随机指令.(当它是某种"goto"时总是很棒.上帝知道它会在哪里结束以及在那之后会发生什么)
代码和数据之间确实没有分离.一切都是一条指令(即使它只是一个NOP),一个指针和一个普通的旧数字.并且代码可能会在您眼前改变.
请帮我搞一个Lisp场景我一直在摸不着头脑.说我有以下程序:
(defun factorial (n)
(if (<= n 1)
1
(* n (factorial (- n 1)))))
; -- Demonstrate the output of factorial --
; -- The part that does the Self modifying goes here –
; -- Demonstrate the changed output of factorial
Run Code Online (Sandbox Code Playgroud)
现在我想要发生的是在这个程序中添加一些Lisp代码,它会将*更改为+,将<=更改为a> =,在那里的某处粘贴一个(+ 1 2 3),并且通常会对函数进行操作起来.然后我希望程序执行结果的绝对混乱.
关键点:除非我在示例代码中犯了一些致命错误,否则您只能更改该-– More code goes here –-部分.你在上面看到的是代码.我不希望你引用整个列表并将其存储在变量中,以便可以将其作为具有相同名称的单独函数进行操作和吐出; 我不希望将阶乘的标准重新定义视为完全不同的东西.我想要那些代码,就在那里,我可以在屏幕上看到我在眼前改变自己,就像机器代码一样.
如果这是一个不可能/不合理的请求,那么它只会在我的脑海中进一步巩固Homoiconicity不是语言有或没有的离散属性的想法,它是一个谱,而Lisp并不处于最前沿.(或者Lisp就像他们来的同性恋,我正在寻找一些其他术语来描述机器代码式的自我修改)
我试图解决最大子序列和问题,并提出了一个neato解决方案
msss :: (Ord a, Num a) => [a] -> a
msss = f 0 0
f gmax _ [] = gmax
f gmax lmax (x:xs) =
let g = max (lmax + x)
in f (g gmax) (g 0) xs
Run Code Online (Sandbox Code Playgroud)
您调用包装函数msss,然后调用f该函数,然后实际执行该工作.解决方案很好,afaik工作正常.如果由于某种原因我必须解决生产代码中的最大子序列和问题,那就是我会这样做的.
然而,包装函数确实让我感到困惑.我喜欢它如何在haskell中,如果你足够坚持,你可以将你的整个程序写在一条线上,真正让家庭认为程序几乎只是一个大表达.所以我想我会尝试消除额外挑战的包装函数.
现在我遇到了经典问题:如何进行匿名递归?当你不能给函数命名时,你如何做递归?值得庆幸的是,计算机的父亲在很久以前通过发现定点组合器来解决这个问题,其中最受欢迎的是Y Combinator.
我已经做了各种尝试来设置Y组合器,但它们无法通过编译器.
msss' :: [Int] -> Int
msss' = (\y f x -> f (y y f) x)
(\y f x -> f (y y f) …Run Code Online (Sandbox Code Playgroud) recursion haskell functional-programming y-combinator anonymous-recursion
每当我开始学习语言时,我做的第一件事就是生成一个用该语言编写的可执行文件(可能是一个已编译的程序或一个脚本),当运行打印'hello,world'和stdout的换行符时:
theironknuckle@beastbook:~/Code$ ./hello
hello, world
Run Code Online (Sandbox Code Playgroud)
在使用GNU Smalltalk大约一个小时后,我还没有发现如何做到这一点.
(我知道你好世界节目可以在会话中表达为
'hello, world' printNl
Run Code Online (Sandbox Code Playgroud)
这不符合我的标准要求)
据我所知,Smalltalk没有主线.所以我非常感兴趣的是可能需要什么类型的样板来实现它.同样,该文件不一定必须编译,但练习的最终结果必须是导致上述会话提取的smalltalk代码.
PS.yesyesyes 我知道我没有接受"基于图像的编程"哲学,这是错误的.我不在乎.我并不反对学习如何使用图像和IDE以及所有这些,但我现在对它的兴趣微乎其微.我关心的是Smalltalk语言本身.在语法上,哲学上和印刷上它是相当美丽的.从命令行解释器和文本编辑器学习编程语言我感到很自在.:)
putStrLn当使用任何参数调用时,将始终返回type的值IO ().我同意这是纯粹的,我可以处理.但它是否具有参考透明度?我是这么认为的,因为对于任何给定的输入,你可以用一个IO ()将在stdout抛出正确字符串的函数调用替换.
所以我很酷putStrLn,但是getLine当没有参数调用时可以返回任何数量的东西,只要它们是类型的IO String.这既不是纯粹的,也不是引用透明的吗?
愚蠢的迂腐问题,它可能不会改变我编写代码的方式,但我真的想要一劳永逸地解决这个问题.(我知道IO monad会正确排序,这不是我的问题)
这为我提出了另一个问题.编译器是否足够智能以识别不带输入的程序?比如说我编译
main = putStrLn . show $ map (+1) [1..10]
Run Code Online (Sandbox Code Playgroud)
GHC是否足够聪明,可以将该程序减少到IO ()导致[2,3,4,5,6,7,8,9,10,11]打印出来的程序?或者它仍在运行并在运行时评估/执行所有内容?对于不需要输入的任意程序也是如此.GHC是否采用了这样一个事实:整个程序是透明的,并且可以简单地用它的价值取代?
haskell functional-programming side-effects referential-transparency
从VBA帮助文件:
GoTo声明
无条件地分支到过程中的指定行.
句法
GoTo _ line _
必需的行参数可以是任何行标签或行号.
备注
GoTo只能分支到它出现的过程中的行.
我的问题是,如何使用跳转到行号GoTo?(我知道如何跳转到标签.)
(注意:为了好奇,我问这个.我无意以GoTo这种方式使用.)
我一直想知道Haskell异常系统如何适应整个"纯函数式语言"的东西.例如,请参阅下面的GHCi会话.
GHCi, version 8.0.1: http://www.haskell.org/ghc/ :? for help
Prelude> head []
*** Exception: Prelude.head: empty list
Prelude> :t head
head :: [a] -> a
Prelude> :t error
error :: [Char] -> a
Prelude> error "ranch"
*** Exception: ranch
CallStack (from HasCallStack):
error, called at <interactive>:4:1 in interactive:Ghci1
Prelude>
Run Code Online (Sandbox Code Playgroud)
头的类型是[a] - > a.但是当你在空列表的特殊情况下调用它时,你会得到一个例外.但是类型签名中没有考虑此异常.
如果我没记错的话,在模式匹配过程中出现故障时,情况类似.类型签名所说的并不重要,如果你没有考虑到每种可能的模式,你就有可能抛出异常.
我没有一个简明扼要的问题要问,但我的头脑正在游泳.将这个奇怪的异常系统添加到其他纯粹优雅语言的动机是什么?它仍然是纯净的,但我只是缺少一些东西?如果我想利用这个异常功能,我将如何去做(即如何捕获和处理异常?还有什么我可以用它们做的吗?)例如,如果我编写使用它的代码"头"功能,当然我应该采取预防措施,以一个空列表以某种方式走私自己的情况.
error-handling haskell functional-programming exception purely-functional