I know a few programmers who keep talking about Haskell when they are among themselves, and here on SO everyone seems to love that language. Being good at Haskell seems somewhat like the hallmark of a genius programmer.
我知道一些程序员在他们自己之间一直在谈论Haskell,而在这里所有人似乎都喜欢这种语言。擅长Haskell似乎有点像天才程序员的标志。
Can someone give a few Haskell examples that show why it is so elegant / superior?
有人可以提供一些Haskell示例,说明为什么它如此优雅/优越?
17 个解决方案
#1
The way it was pitched to me, and what I think is true after having worked on learning on Haskell for a month now, is the fact that functional programming twists your brain in interesting ways: it forces you to think about familiar problems in different ways: instead of loops, think in maps and folds and filters, etc. In general, if you have more than one perspective on a problem, it makes you better enabled to reason about this problem, and switch viewpoints as necessary.
在我学习Haskell一个月之后,它对我的态度以及我的想法是正确的,因为函数式编程以有趣的方式扭曲了你的大脑:它迫使你以不同的方式思考熟悉的问题:而不是循环,请考虑地图和折叠和过滤器等。通常,如果您对问题有多个透视图,则可以更好地解决此问题,并根据需要切换视点。
The other really neat thing about Haskell is its type system. It's strictly typed, but the type inference engine makes it feel like a Python program that magically tells you when you've done a stupid type-related mistake. Haskell's error messages in this regard are somewhat lacking, but as you get more acquainted with the language you'll say to yourself: this is what typing is supposed to be!
关于Haskell的另一个非常巧妙的事情是它的类型系统。它是严格类型的,但类型推理引擎让它感觉像一个Python程序,当你做了一个与愚蠢的类型相关的错误时,它会神奇地告诉你。 Haskell在这方面的错误信息有点缺乏,但随着你越来越熟悉你会对自己说的语言:这就是打字应该是什么!
#2
This is the example that convinced me to learn Haskell (and boy am I glad I did).
这是说服我学习Haskell的例子(男孩,我很高兴我做过)。
-- program to copy a file --
import System.Environment
main = do
--read command-line arguments
[file1, file2] <- getArgs
--copy file contents
str <- readFile file1
writeFile file2 str
OK, it's a short, readable program. In that sense it's better than a C program. But how is this so different from (say) a Python program with a very similar structure?
好的,这是一个简短易读的程序。从这个意义上说,它比C程序更好。但是,与具有非常相似结构的Python程序有什么不同呢?
The answer is lazy evaluation. In most languages (even some functional ones), a program structured like the one above would result in the entire file being loaded into memory, and then written out again under a new name.
答案是懒惰的评价。在大多数语言(甚至一些功能语言)中,如上所述的程序将导致整个文件被加载到内存中,然后以新名称再次写出。
Haskell is "lazy". It doesn't calculate things until it needs to, and by extension doesn't calculate things it never needs. For instance, if you were to remove the writeFile
line, Haskell wouldn't bother reading anything from the file in the first place.
哈斯克尔是“懒惰的”。它不会在需要之前计算事物,并且通过扩展不计算它永远不需要的东西。例如,如果要删除writeFile行,Haskell首先不会从文件中读取任何内容。
As it is, Haskell realises that the writeFile
depends on the readFile
, and so is able to optimise this data path.
实际上,Haskell意识到writeFile依赖于readFile,因此能够优化此数据路径。
While the results are compiler-dependent, what will typically happen when you run the above program is this: the program reads a block (say 8KB) of the first file, then writes it to the second file, then reads another block from the first file, and writes it to the second file, and so on. (Try running strace
on it!)
虽然结果依赖于编译器,但运行上述程序时通常会发生这种情况:程序读取第一个文件的块(比如8KB),然后将其写入第二个文件,然后从第一个文件读取另一个块文件,并将其写入第二个文件,依此类推。 (尝试在它上面运行strace!)
... which looks a lot like what the efficient C implementation of a file copy would do.
...看起来很像文件副本的高效C实现会做什么。
So, Haskell lets you write compact, readable programs - often without sacrificing a lot of performance.
因此,Haskell允许您编写紧凑,可读的程序 - 通常不会牺牲很多性能。
Another thing I must add is that Haskell simply makes it difficult to write buggy programs. The amazing type system, lack of side-effects, and of course the compactness of Haskell code reduces bugs for at least three reasons:
我必须补充的另一件事是Haskell只是让编写错误程序变得困难。令人惊讶的类型系统,缺乏副作用,当然还有Haskell代码的紧凑性,至少有三个原因:
-
Better program design. Reduced complexity leads to less logic errors.
更好的程序设计。复杂性降低导致逻辑错误减少。
-
Compact code. Less lines for bugs to exist on.
紧凑的代码。减少存在错误的行数。
-
Compile errors. Lots of bugs just aren't valid Haskell.
编译错误。很多bug都不是有效的Haskell。
Haskell isn't for everyone. But everyone should give it a try.
Haskell并不适合所有人。但是每个人都应该尝试一下。
#3
You are kind of asking the wrong question.
你有点问错误的问题。
Haskell is not a language where you go look at a few cool examples and go "aha, I see now, that's what makes it good!"
Haskell不是一种语言,你可以去看几个很酷的例子然后去“啊哈,我现在看,这就是它的好处!”
It's more like, we have all these other programming languages, and they're all more or less similar, and then there's Haskell which is totally different and wacky in a way that's totally awesome once you get used to the wackiness. But the problem is, it takes quite a while to acclimate to the wackiness. Things that set Haskell apart from almost any other even-semi-mainstream language:
它更像是,我们拥有所有这些其他编程语言,并且它们或多或少相似,然后就是Haskell完全不同和古怪,一旦你习惯了古怪就会非常棒。但问题是,适应这种古怪需要一段时间。使Haskell与几乎任何其他甚至半主流语言区别开来的事情:
- Lazy evaluation
- No side effects (everything is pure, IO/etc happens via monads)
- Incredibly expressive static type system
没有副作用(一切都是纯粹的,IO /等通过monad发生)
令人难以置信的表达静态类型系统
as well as some other aspects that are different from many mainstream languages (but shared by some):
以及与许多主流语言不同的一些其他方面(但由一些人共享):
- functional
- significant whitespace
- type inferred
As some other posters have answered, the combination of all these features means that you think about programming in an entirely different way. And so it's hard to come up with an example (or set of examples) that adequately communicates this to Joe-mainstream-programmer. It's an experiential thing. (To make an analogy, I can show you photos of my 1970 trip to China, but after seeing the photos, you still won't know what it was like to have lived there during that time. Similarly, I can show you a Haskell 'quicksort', but you still won't know what it means to be a Haskeller.)
正如其他一些海报所回答的那样,所有这些功能的结合意味着您以完全不同的方式思考编程。所以很难想出一个例子(或一组例子),这些例子可以充分地传达给Joe-主流程序员。这是一个体验式的事情。 (为了比喻一下,我可以向你展示1970年中国之行的照片,但在看完这些照片之后,你仍然不知道在那段时间里住在那里是什么样的。同样,我可以告诉你一个Haskell 'quicksort',但你仍然不知道成为Haskeller是什么意思。)
#4
What really sets Haskell apart is the effort it goes to in its design to enforce functional programming. You can program in a functional style in pretty much any language, but it's all too easy to abandon at the first convenience. Haskell does not allow you to abandon functional programming, so you must take it to its logical conclusion, which is a final program that is easier to reason about, and sidesteps a whole class of the thorniest types of bugs.
真正让Haskell与众不同的是它在设计中为实现函数式编程所付出的努力。您可以使用几乎任何语言编写功能样式,但在第一次使用时很容易放弃。 Haskell不允许你放弃函数式编程,所以你必须把它归结为逻辑结论,这是一个更容易推理的最终程序,并回避了一大类最棘手的bug。
When it comes to writing a program for real world use, you may find Haskell lacking in some practical fashion, but your final solution will be better for having known Haskell to begin with. I'm definitely not there yet, but so far learning Haskell has been much more enlightening than say, Lisp was in college.
当编写一个用于实际使用的程序时,您可能会发现Haskell缺乏某种实用的方式,但是最终的解决方案对于开始使用Haskell会更好。我肯定不在那里,但到目前为止,学习Haskell比说起来更有启发性,Lisp在大学里。
#5
Part of the fuss is that purity and static typing enable for parallelism combined with aggressive optimisations. Parallel languages are hot now with multicore being a bit disruptive.
大惊小怪的部分是纯度和静态类型使并行性与积极的优化相结合。并行语言现在很热门,多核有点破坏性。
Haskell gives you more options for parallelism than pretty much any general purpose language, along with a fast, native code compiler. There is really no competition with this kind of support for parallel styles:
与任何通用语言相比,Haskell为您提供了更多的并行选项,以及快速的本机代码编译器。这种对并行样式的支持确实没有竞争:
- semi-implicit parallelism via thread sparks
- explicit threads
- data parallel arrays
- actors and message passing
- transactional memory
通过线程火花的半隐式并行性
数据并行数组
演员和消息传递
So if you care about making your multicore work, Haskell has something to say. A great place to start is with Simon Peyton Jones' tutorial on parallel and concurrent programming in Haskell.
因此,如果你关心让你的多核工作,Haskell有话要说。一个很好的起点是Simon Peyton Jones关于Haskell并行和并发编程的教程。
#6
I've spent the last year learning Haskell and writing a reasonably large and complex project in it. (The project is an automated options trading system, and everything from the trading algorithms to the parsing and handling of low-level, high-speed market data feeds is done in Haskell.) It's considerably more concise and easier to understand (for those with appropriate background) than a Java version would be, as well as extremely robust.
去年我花了很多时间学习Haskell并在其中编写一个相当大而复杂的项目。 (该项目是一个自动化的期权交易系统,从交易算法到解析和处理低级,高速市场数据源的所有内容都在Haskell中完成。)它更简洁,更容易理解(对于那些适当的背景)比Java版本,以及非常强大。
Possibly the biggest win for me has been the ability to modularize control flow through things such as monoids, monads, and so on. A very simple example would be the Ordering monoid; in an expression such as
可能对我来说最大的胜利就是能够通过诸如幺半群,monad等事物来模块化控制流。一个非常简单的例子是Ordering monoid;在诸如的表达中
c1 `mappend` c2 `mappend` c3
where c1
and so on return LT
, EQ
or GT
, c1
returning EQ
causes the expression to continue, evaluating c2
; if c2
returns LT
or GT
that's the value of the whole, and c3
is not evaluated. This sort of thing gets considerably more sophisticated and complex in things like monadic message generators and parsers where I may be carrying around different types of state, have varying abort conditions, or may want to be able to decide for any particular call whether abort really means "no further processing" or means, "return an error at the end, but carry on processing to collect further error messages."
其中c1等返回LT,EQ或GT,c1返回EQ导致表达式继续,评估c2;如果c2返回的LT或GT是整体的值,则不评估c3。像monadic消息生成器和解析器这样的东西变得相当复杂和复杂,我可能会携带不同类型的状态,有不同的中止条件,或者可能希望能够决定是否中止真正意味着任何特定的调用“没有进一步处理”或意味着“最后返回错误,但继续处理以收集进一步的错误消息。”
This is all stuff it takes some time and probably quite some effort to learn, and thus it can be hard to make a convincing argument for it for those who don't already know these techniques. I think that the All About Monads tutorial gives a pretty impressive demonstration of one facet of this, but I wouldn't expect that anybody not familiar with the material already would "get it" on the first, or even the third, careful reading.
这是所有需要花费一些时间的东西,可能需要花费很多精力来学习,因此对于那些不熟悉这些技术的人来说,很难为它做出令人信服的论证。我认为All About Monads教程给出了一个相当令人印象深刻的演示,但我不希望任何不熟悉这些材料的人已经在第一次,甚至是第三次仔细阅读中“得到它”。
Anyway, there's lots of other good stuff in Haskell as well, but this is a major one that I don't see mentioned so often, probably because it's rather complex.
无论如何,Haskell中还有很多其他好东西,但这是一个我不经常提到的主要内容,可能是因为它相当复杂。
#7
Software Transactional Memory is a pretty cool way to deal with concurrency. It's much more flexible than message passing, and not deadlock prone like mutexes. GHC's implementation of STM is considered one of the best.
软件事务内存是处理并发的一种非常酷的方法。它比消息传递更灵活,而不像互斥体那样容易出现死锁。 GHC对STM的实施被认为是最好的之一。
#8
For an interesting example you can look at: http://en.literateprograms.org/Quicksort_(Haskell)
有关一个有趣的例子,你可以看看:http://en.literateprograms.org/Quicksort_(Hackask)
What is interesting is to look at the implementation in various languages.
有趣的是以各种语言查看实现。
What makes Haskell so interesting, along with other functional languages, is the fact that you have to think differently about how to program. For example, you will generally not use for or while loops, but will use recursion.
让Haskell与其他函数语言一起变得如此有趣的原因在于,您必须对如何编程进行不同的思考。例如,您通常不会使用for或while循环,但会使用递归。
As is mentioned above, Haskell and other functional languages excel with parallel processing and writing applications to work on multi-cores.
如上所述,Haskell和其他功能语言在并行处理和编写应用程序方面表现优异,可用于多核。
#9
I couldn't give you an example, I'm an OCaml guy, but when I'm in such a situation as yourself, curiosity just takes hold and I have to download a compiler/interpreter and give it a go. You'll likely learn far more that way about the strengths and weaknesses of a given functional language.
我不能给你一个例子,我是一个OCaml家伙,但是当我遇到像你这样的情况时,好奇心刚刚掌握,我必须下载一个编译器/解释器并试一试。您可能会更多地了解给定功能语言的优点和缺点。
#10
One thing I find very cool when dealing with algorithms or mathematical problems is Haskell's inherent lazy evaluation of computations, which is only possible due to its strict functional nature.
在处理算法或数学问题时,我发现非常酷的一件事是Haskell对计算的固有懒惰评估,这只能由于其严格的功能性而成为可能。
For example, if you want to calculate all primes, you could use
例如,如果要计算所有素数,可以使用
primes = sieve [2..]
where sieve (p:xs) = p : sieve [x | x<-xs, x `mod` p /= 0]
and the result is actually an infinite list. But Haskell will evaluate it left from right, so as long as you don't try to do something that requires the entire list, you can can still use it without the program getting stuck in infinity, such as:
结果实际上是一个无限的列表。但是Haskell会从右边评估它,所以只要你不尝试做一些需要整个列表的东西,你仍然可以使用它而不会让程序陷入无穷大,例如:
foo = sum $ takeWhile (<100) primes
which sums all primes less than 100. This is nice for several reasons. First of all, I only need to write one prime function that generates all primes and then I'm pretty much ready to work with primes. In an object-oriented programming language, I would need some way to tell the function how many primes it should compute before returning, or emulate the infinite list behavior with an object. Another thing is that in general, you end up writing code that expresses what you want to compute and not in which order to evaluate things - instead the compiler does that for you.
它总和所有小于100的素数。这很好,有几个原因。首先,我只需编写一个生成所有素数的素数函数,然后我就可以使用素数了。在面向对象的编程语言中,我需要一些方法来告诉函数在返回之前应该计算多少素数,或者用对象模拟无限列表行为。另一件事是,一般来说,你最终会编写表达你想要计算的东西的代码而不是用于评估事物的顺序 - 而编译器会为你做这些。
This is not only useful for infinite lists, in fact it gets used without you knowing it all the time when there is no need to evaluate more than necessary.
这不仅对无限列表有用,实际上它是在没有必要时不需要进行评估的情况下一直使用的。
#11
I agree with others that seeing a few small examples is not the best way to show off Haskell. But I'll give some anyway. Here's a lightning-fast solution to Euler Project problems 18 and 67, which ask you to find the maximum-sum path from the base to the apex of a triangle:
我同意其他人的观点,看到一些小例子并不是展示Haskell的最佳方式。但无论如何我会给一些。这是Euler Project问题18和67的快速解决方案,它要求您找到从三角形的基线到顶点的最大和路径:
bottomUp :: (Ord a, Num a) => [[a]] -> a
bottomUp = head . bu
where bu [bottom] = bottom
bu (row : base) = merge row $ bu base
merge [] [_] = []
merge (x:xs) (y1:y2:ys) = x + max y1 y2 : merge xs (y2:ys)
Here is a complete, reusable implementation of the BubbleSearch algorithm by Lesh and Mitzenmacher. I used it to pack large media files for archival storage on DVD with no waste:
这是Lesh和Mitzenmacher对BubbleSearch算法的完整,可重用的实现。我使用它来打包大型媒体文件,以便在DVD上存档,而不会浪费:
data BubbleResult i o = BubbleResult { bestResult :: o
, result :: o
, leftoverRandoms :: [Double]
}
bubbleSearch :: (Ord result) =>
([a] -> result) -> -- greedy search algorithm
Double -> -- probability
[a] -> -- list of items to be searched
[Double] -> -- list of random numbers
[BubbleResult a result] -- monotone list of results
bubbleSearch search p startOrder rs = bubble startOrder rs
where bubble order rs = BubbleResult answer answer rs : walk tries
where answer = search order
tries = perturbations p order rs
walk ((order, rs) : rest) =
if result > answer then bubble order rs
else BubbleResult answer result rs : walk rest
where result = search order
perturbations :: Double -> [a] -> [Double] -> [([a], [Double])]
perturbations p xs rs = xr' : perturbations p xs (snd xr')
where xr' = perturb xs rs
perturb :: [a] -> [Double] -> ([a], [Double])
perturb xs rs = shift_all p [] xs rs
shift_all p new' [] rs = (reverse new', rs)
shift_all p new' old rs = shift_one new' old rs (shift_all p)
where shift_one :: [a] -> [a] -> [Double] -> ([a]->[a]->[Double]->b) -> b
shift_one new' xs rs k = shift new' [] xs rs
where shift new' prev' [x] rs = k (x:new') (reverse prev') rs
shift new' prev' (x:xs) (r:rs)
| r <= p = k (x:new') (prev' `revApp` xs) rs
| otherwise = shift new' (x:prev') xs rs
revApp xs ys = foldl (flip (:)) ys xs
I'm sure this code looks like random gibberish. But if you read Mitzenmacher's blog entry and understand the algorithm, you'll be amazed that it's possible to package the algorithm into code without saying anything about what you're searching for.
我确定这段代码看起来像随意的乱码。但是,如果您阅读Mitzenmacher的博客条目并理解该算法,您会惊讶于可以将算法打包到代码中,而无需说明您要搜索的内容。
Having given you some examples as you asked for, I will say that the best way to start to appreciate Haskell is to read the paper that gave me the ideas I needed to write the DVD packer: Why Functional Programming Matters by John Hughes. The paper actually predates Haskell, but it brilliantly explains some of the ideas that make people like Haskell.
根据你的要求给了你一些例子,我会说开始欣赏Haskell的最好方法是阅读那些给我写DVD包装器所需要的想法的文章:为什么功能编程很重要John Hughes。这篇论文实际上早于Haskell,但它巧妙地解释了一些让人们喜欢Haskell的想法。
#12
For me, the attraction of Haskell is the promise of compiler guaranteed correctness. Even if it is for pure parts of the code.
对我来说,Haskell的吸引力在于编译器保证正确性的承诺。即使它是代码的纯部分。
I have written a lot of scientific simulation code, and have wondered so many times if there was a bug in my prior codes, which could invalidate a lot of current work.
我已经写了很多科学模拟代码,如果我之前的代码中存在一个错误,那么我已经多次想知道,这可能会使许多当前的工作无效。
#13
I find that for certain tasks I am incredibly productive with Haskell.
我发现对于某些任务,我使用Haskell非常高效。
The reason is because of the succinct syntax and the ease of testing.
原因在于简洁的语法和易于测试。
This is what the function declaration syntax is like:
这就是函数声明语法的含义:
foo a = a + 5
foo a = a + 5
That's is simplest way I can think of defining a function.
这是我能想到定义函数的最简单方法。
If I write the inverse
如果我写逆
inverseFoo a = a - 5
inverseFoo a = a - 5
I can check that it is an inverse for any random input by writing
我可以通过写入来检查它是否是任何随机输入的反转
prop_IsInverse :: Double -> Bool
prop_IsInverse a = a == (inverseFoo $ foo a)prop_IsInverse :: Double - > Bool prop_IsInverse a = a ==(inverseFoo $ foo a)
And calling from the command line
并从命令行调用
jonny@ubuntu: runhaskell quickCheck +names fooFileName.hs
jonny @ ubuntu:runhaskell quickCheck + names fooFileName.hs
Which will check that all the properties in my file are held, by randomly testing inputs a hundred times of so.
这将检查我的文件中的所有属性是否被保留,通过随机测试输入一百次。
I don't think Haskell is the perfect language for everything, but when it comes to writing little functions and testing, I haven't seen anything better. If your programming has a mathematical component this is very important.
我不认为Haskell是所有内容的完美语言,但是当谈到编写小函数和测试时,我还没有看到更好的东西。如果您的编程具有数学成分,则这非常重要。
#14
If you can wrap your head around the type system in Haskell I think that in itself is quite an accomplishment.
如果你可以在Haskell中绕过类型系统,我认为这本身就是一个很大的成就。
#15
it has no loop constructs. not many languages have this trait.
它没有循环结构。没有多少语言有这个特点。
#16
I agree with those that said that functional programming twists your brain into seeing programming from a different angle. I've only used it as a hobbyist, but I think it fundamentally changed the way I approach a problem. I don't think I would have been nearly as effective with LINQ without having been exposed to Haskell (and using generators and list comprehensions in Python).
我同意那些说功能编程能够让你的大脑从不同角度看编程的人。我只把它用作业余爱好者,但我认为它从根本上改变了我解决问题的方式。如果没有暴露给Haskell(并在Python中使用生成器和列表推导),我认为我对LINQ几乎没有那么有效。
#17
To air a contrarian view: Steve Yegge writes that Hindely-Milner languages lack the flexibility required to write good systems:
提出逆向观点:Steve Yegge写道,Hindely-Milner语言缺乏编写好系统所需的灵活性:
H-M is very pretty, in a totally useless formal mathematical sense. It handles a few computation constructs very nicely; the pattern matching dispatch found in Haskell, SML and OCaml is particularly handy. Unsurprisingly, it handles some other common and highly desirable constructs awkwardly at best, but they explain those scenarios away by saying that you're mistaken, you don't actually want them. You know, things like, oh, setting variables.
H-M非常漂亮,完全无用的正式数学意义。它很好地处理了一些计算结构;在Haskell,SML和OCaml中找到的模式匹配调度特别方便。不出所料,它充其量只是笨拙地处理其他一些常见且非常理想的结构,但是他们通过说你错了,你实际上并不想要它们来解释这些情况。你知道,哦,设置变量。
Haskell is worth learning, but it has its own weaknesses.
Haskell值得学习,但它有自己的弱点。
#1
The way it was pitched to me, and what I think is true after having worked on learning on Haskell for a month now, is the fact that functional programming twists your brain in interesting ways: it forces you to think about familiar problems in different ways: instead of loops, think in maps and folds and filters, etc. In general, if you have more than one perspective on a problem, it makes you better enabled to reason about this problem, and switch viewpoints as necessary.
在我学习Haskell一个月之后,它对我的态度以及我的想法是正确的,因为函数式编程以有趣的方式扭曲了你的大脑:它迫使你以不同的方式思考熟悉的问题:而不是循环,请考虑地图和折叠和过滤器等。通常,如果您对问题有多个透视图,则可以更好地解决此问题,并根据需要切换视点。
The other really neat thing about Haskell is its type system. It's strictly typed, but the type inference engine makes it feel like a Python program that magically tells you when you've done a stupid type-related mistake. Haskell's error messages in this regard are somewhat lacking, but as you get more acquainted with the language you'll say to yourself: this is what typing is supposed to be!
关于Haskell的另一个非常巧妙的事情是它的类型系统。它是严格类型的,但类型推理引擎让它感觉像一个Python程序,当你做了一个与愚蠢的类型相关的错误时,它会神奇地告诉你。 Haskell在这方面的错误信息有点缺乏,但随着你越来越熟悉你会对自己说的语言:这就是打字应该是什么!
#2
This is the example that convinced me to learn Haskell (and boy am I glad I did).
这是说服我学习Haskell的例子(男孩,我很高兴我做过)。
-- program to copy a file --
import System.Environment
main = do
--read command-line arguments
[file1, file2] <- getArgs
--copy file contents
str <- readFile file1
writeFile file2 str
OK, it's a short, readable program. In that sense it's better than a C program. But how is this so different from (say) a Python program with a very similar structure?
好的,这是一个简短易读的程序。从这个意义上说,它比C程序更好。但是,与具有非常相似结构的Python程序有什么不同呢?
The answer is lazy evaluation. In most languages (even some functional ones), a program structured like the one above would result in the entire file being loaded into memory, and then written out again under a new name.
答案是懒惰的评价。在大多数语言(甚至一些功能语言)中,如上所述的程序将导致整个文件被加载到内存中,然后以新名称再次写出。
Haskell is "lazy". It doesn't calculate things until it needs to, and by extension doesn't calculate things it never needs. For instance, if you were to remove the writeFile
line, Haskell wouldn't bother reading anything from the file in the first place.
哈斯克尔是“懒惰的”。它不会在需要之前计算事物,并且通过扩展不计算它永远不需要的东西。例如,如果要删除writeFile行,Haskell首先不会从文件中读取任何内容。
As it is, Haskell realises that the writeFile
depends on the readFile
, and so is able to optimise this data path.
实际上,Haskell意识到writeFile依赖于readFile,因此能够优化此数据路径。
While the results are compiler-dependent, what will typically happen when you run the above program is this: the program reads a block (say 8KB) of the first file, then writes it to the second file, then reads another block from the first file, and writes it to the second file, and so on. (Try running strace
on it!)
虽然结果依赖于编译器,但运行上述程序时通常会发生这种情况:程序读取第一个文件的块(比如8KB),然后将其写入第二个文件,然后从第一个文件读取另一个块文件,并将其写入第二个文件,依此类推。 (尝试在它上面运行strace!)
... which looks a lot like what the efficient C implementation of a file copy would do.
...看起来很像文件副本的高效C实现会做什么。
So, Haskell lets you write compact, readable programs - often without sacrificing a lot of performance.
因此,Haskell允许您编写紧凑,可读的程序 - 通常不会牺牲很多性能。
Another thing I must add is that Haskell simply makes it difficult to write buggy programs. The amazing type system, lack of side-effects, and of course the compactness of Haskell code reduces bugs for at least three reasons:
我必须补充的另一件事是Haskell只是让编写错误程序变得困难。令人惊讶的类型系统,缺乏副作用,当然还有Haskell代码的紧凑性,至少有三个原因:
-
Better program design. Reduced complexity leads to less logic errors.
更好的程序设计。复杂性降低导致逻辑错误减少。
-
Compact code. Less lines for bugs to exist on.
紧凑的代码。减少存在错误的行数。
-
Compile errors. Lots of bugs just aren't valid Haskell.
编译错误。很多bug都不是有效的Haskell。
Haskell isn't for everyone. But everyone should give it a try.
Haskell并不适合所有人。但是每个人都应该尝试一下。
#3
You are kind of asking the wrong question.
你有点问错误的问题。
Haskell is not a language where you go look at a few cool examples and go "aha, I see now, that's what makes it good!"
Haskell不是一种语言,你可以去看几个很酷的例子然后去“啊哈,我现在看,这就是它的好处!”
It's more like, we have all these other programming languages, and they're all more or less similar, and then there's Haskell which is totally different and wacky in a way that's totally awesome once you get used to the wackiness. But the problem is, it takes quite a while to acclimate to the wackiness. Things that set Haskell apart from almost any other even-semi-mainstream language:
它更像是,我们拥有所有这些其他编程语言,并且它们或多或少相似,然后就是Haskell完全不同和古怪,一旦你习惯了古怪就会非常棒。但问题是,适应这种古怪需要一段时间。使Haskell与几乎任何其他甚至半主流语言区别开来的事情:
- Lazy evaluation
- No side effects (everything is pure, IO/etc happens via monads)
- Incredibly expressive static type system
没有副作用(一切都是纯粹的,IO /等通过monad发生)
令人难以置信的表达静态类型系统
as well as some other aspects that are different from many mainstream languages (but shared by some):
以及与许多主流语言不同的一些其他方面(但由一些人共享):
- functional
- significant whitespace
- type inferred
As some other posters have answered, the combination of all these features means that you think about programming in an entirely different way. And so it's hard to come up with an example (or set of examples) that adequately communicates this to Joe-mainstream-programmer. It's an experiential thing. (To make an analogy, I can show you photos of my 1970 trip to China, but after seeing the photos, you still won't know what it was like to have lived there during that time. Similarly, I can show you a Haskell 'quicksort', but you still won't know what it means to be a Haskeller.)
正如其他一些海报所回答的那样,所有这些功能的结合意味着您以完全不同的方式思考编程。所以很难想出一个例子(或一组例子),这些例子可以充分地传达给Joe-主流程序员。这是一个体验式的事情。 (为了比喻一下,我可以向你展示1970年中国之行的照片,但在看完这些照片之后,你仍然不知道在那段时间里住在那里是什么样的。同样,我可以告诉你一个Haskell 'quicksort',但你仍然不知道成为Haskeller是什么意思。)
#4
What really sets Haskell apart is the effort it goes to in its design to enforce functional programming. You can program in a functional style in pretty much any language, but it's all too easy to abandon at the first convenience. Haskell does not allow you to abandon functional programming, so you must take it to its logical conclusion, which is a final program that is easier to reason about, and sidesteps a whole class of the thorniest types of bugs.
真正让Haskell与众不同的是它在设计中为实现函数式编程所付出的努力。您可以使用几乎任何语言编写功能样式,但在第一次使用时很容易放弃。 Haskell不允许你放弃函数式编程,所以你必须把它归结为逻辑结论,这是一个更容易推理的最终程序,并回避了一大类最棘手的bug。
When it comes to writing a program for real world use, you may find Haskell lacking in some practical fashion, but your final solution will be better for having known Haskell to begin with. I'm definitely not there yet, but so far learning Haskell has been much more enlightening than say, Lisp was in college.
当编写一个用于实际使用的程序时,您可能会发现Haskell缺乏某种实用的方式,但是最终的解决方案对于开始使用Haskell会更好。我肯定不在那里,但到目前为止,学习Haskell比说起来更有启发性,Lisp在大学里。
#5
Part of the fuss is that purity and static typing enable for parallelism combined with aggressive optimisations. Parallel languages are hot now with multicore being a bit disruptive.
大惊小怪的部分是纯度和静态类型使并行性与积极的优化相结合。并行语言现在很热门,多核有点破坏性。
Haskell gives you more options for parallelism than pretty much any general purpose language, along with a fast, native code compiler. There is really no competition with this kind of support for parallel styles:
与任何通用语言相比,Haskell为您提供了更多的并行选项,以及快速的本机代码编译器。这种对并行样式的支持确实没有竞争:
- semi-implicit parallelism via thread sparks
- explicit threads
- data parallel arrays
- actors and message passing
- transactional memory
通过线程火花的半隐式并行性
数据并行数组
演员和消息传递
So if you care about making your multicore work, Haskell has something to say. A great place to start is with Simon Peyton Jones' tutorial on parallel and concurrent programming in Haskell.
因此,如果你关心让你的多核工作,Haskell有话要说。一个很好的起点是Simon Peyton Jones关于Haskell并行和并发编程的教程。
#6
I've spent the last year learning Haskell and writing a reasonably large and complex project in it. (The project is an automated options trading system, and everything from the trading algorithms to the parsing and handling of low-level, high-speed market data feeds is done in Haskell.) It's considerably more concise and easier to understand (for those with appropriate background) than a Java version would be, as well as extremely robust.
去年我花了很多时间学习Haskell并在其中编写一个相当大而复杂的项目。 (该项目是一个自动化的期权交易系统,从交易算法到解析和处理低级,高速市场数据源的所有内容都在Haskell中完成。)它更简洁,更容易理解(对于那些适当的背景)比Java版本,以及非常强大。
Possibly the biggest win for me has been the ability to modularize control flow through things such as monoids, monads, and so on. A very simple example would be the Ordering monoid; in an expression such as
可能对我来说最大的胜利就是能够通过诸如幺半群,monad等事物来模块化控制流。一个非常简单的例子是Ordering monoid;在诸如的表达中
c1 `mappend` c2 `mappend` c3
where c1
and so on return LT
, EQ
or GT
, c1
returning EQ
causes the expression to continue, evaluating c2
; if c2
returns LT
or GT
that's the value of the whole, and c3
is not evaluated. This sort of thing gets considerably more sophisticated and complex in things like monadic message generators and parsers where I may be carrying around different types of state, have varying abort conditions, or may want to be able to decide for any particular call whether abort really means "no further processing" or means, "return an error at the end, but carry on processing to collect further error messages."
其中c1等返回LT,EQ或GT,c1返回EQ导致表达式继续,评估c2;如果c2返回的LT或GT是整体的值,则不评估c3。像monadic消息生成器和解析器这样的东西变得相当复杂和复杂,我可能会携带不同类型的状态,有不同的中止条件,或者可能希望能够决定是否中止真正意味着任何特定的调用“没有进一步处理”或意味着“最后返回错误,但继续处理以收集进一步的错误消息。”
This is all stuff it takes some time and probably quite some effort to learn, and thus it can be hard to make a convincing argument for it for those who don't already know these techniques. I think that the All About Monads tutorial gives a pretty impressive demonstration of one facet of this, but I wouldn't expect that anybody not familiar with the material already would "get it" on the first, or even the third, careful reading.
这是所有需要花费一些时间的东西,可能需要花费很多精力来学习,因此对于那些不熟悉这些技术的人来说,很难为它做出令人信服的论证。我认为All About Monads教程给出了一个相当令人印象深刻的演示,但我不希望任何不熟悉这些材料的人已经在第一次,甚至是第三次仔细阅读中“得到它”。
Anyway, there's lots of other good stuff in Haskell as well, but this is a major one that I don't see mentioned so often, probably because it's rather complex.
无论如何,Haskell中还有很多其他好东西,但这是一个我不经常提到的主要内容,可能是因为它相当复杂。
#7
Software Transactional Memory is a pretty cool way to deal with concurrency. It's much more flexible than message passing, and not deadlock prone like mutexes. GHC's implementation of STM is considered one of the best.
软件事务内存是处理并发的一种非常酷的方法。它比消息传递更灵活,而不像互斥体那样容易出现死锁。 GHC对STM的实施被认为是最好的之一。
#8
For an interesting example you can look at: http://en.literateprograms.org/Quicksort_(Haskell)
有关一个有趣的例子,你可以看看:http://en.literateprograms.org/Quicksort_(Hackask)
What is interesting is to look at the implementation in various languages.
有趣的是以各种语言查看实现。
What makes Haskell so interesting, along with other functional languages, is the fact that you have to think differently about how to program. For example, you will generally not use for or while loops, but will use recursion.
让Haskell与其他函数语言一起变得如此有趣的原因在于,您必须对如何编程进行不同的思考。例如,您通常不会使用for或while循环,但会使用递归。
As is mentioned above, Haskell and other functional languages excel with parallel processing and writing applications to work on multi-cores.
如上所述,Haskell和其他功能语言在并行处理和编写应用程序方面表现优异,可用于多核。
#9
I couldn't give you an example, I'm an OCaml guy, but when I'm in such a situation as yourself, curiosity just takes hold and I have to download a compiler/interpreter and give it a go. You'll likely learn far more that way about the strengths and weaknesses of a given functional language.
我不能给你一个例子,我是一个OCaml家伙,但是当我遇到像你这样的情况时,好奇心刚刚掌握,我必须下载一个编译器/解释器并试一试。您可能会更多地了解给定功能语言的优点和缺点。
#10
One thing I find very cool when dealing with algorithms or mathematical problems is Haskell's inherent lazy evaluation of computations, which is only possible due to its strict functional nature.
在处理算法或数学问题时,我发现非常酷的一件事是Haskell对计算的固有懒惰评估,这只能由于其严格的功能性而成为可能。
For example, if you want to calculate all primes, you could use
例如,如果要计算所有素数,可以使用
primes = sieve [2..]
where sieve (p:xs) = p : sieve [x | x<-xs, x `mod` p /= 0]
and the result is actually an infinite list. But Haskell will evaluate it left from right, so as long as you don't try to do something that requires the entire list, you can can still use it without the program getting stuck in infinity, such as:
结果实际上是一个无限的列表。但是Haskell会从右边评估它,所以只要你不尝试做一些需要整个列表的东西,你仍然可以使用它而不会让程序陷入无穷大,例如:
foo = sum $ takeWhile (<100) primes
which sums all primes less than 100. This is nice for several reasons. First of all, I only need to write one prime function that generates all primes and then I'm pretty much ready to work with primes. In an object-oriented programming language, I would need some way to tell the function how many primes it should compute before returning, or emulate the infinite list behavior with an object. Another thing is that in general, you end up writing code that expresses what you want to compute and not in which order to evaluate things - instead the compiler does that for you.
它总和所有小于100的素数。这很好,有几个原因。首先,我只需编写一个生成所有素数的素数函数,然后我就可以使用素数了。在面向对象的编程语言中,我需要一些方法来告诉函数在返回之前应该计算多少素数,或者用对象模拟无限列表行为。另一件事是,一般来说,你最终会编写表达你想要计算的东西的代码而不是用于评估事物的顺序 - 而编译器会为你做这些。
This is not only useful for infinite lists, in fact it gets used without you knowing it all the time when there is no need to evaluate more than necessary.
这不仅对无限列表有用,实际上它是在没有必要时不需要进行评估的情况下一直使用的。
#11
I agree with others that seeing a few small examples is not the best way to show off Haskell. But I'll give some anyway. Here's a lightning-fast solution to Euler Project problems 18 and 67, which ask you to find the maximum-sum path from the base to the apex of a triangle:
我同意其他人的观点,看到一些小例子并不是展示Haskell的最佳方式。但无论如何我会给一些。这是Euler Project问题18和67的快速解决方案,它要求您找到从三角形的基线到顶点的最大和路径:
bottomUp :: (Ord a, Num a) => [[a]] -> a
bottomUp = head . bu
where bu [bottom] = bottom
bu (row : base) = merge row $ bu base
merge [] [_] = []
merge (x:xs) (y1:y2:ys) = x + max y1 y2 : merge xs (y2:ys)
Here is a complete, reusable implementation of the BubbleSearch algorithm by Lesh and Mitzenmacher. I used it to pack large media files for archival storage on DVD with no waste:
这是Lesh和Mitzenmacher对BubbleSearch算法的完整,可重用的实现。我使用它来打包大型媒体文件,以便在DVD上存档,而不会浪费:
data BubbleResult i o = BubbleResult { bestResult :: o
, result :: o
, leftoverRandoms :: [Double]
}
bubbleSearch :: (Ord result) =>
([a] -> result) -> -- greedy search algorithm
Double -> -- probability
[a] -> -- list of items to be searched
[Double] -> -- list of random numbers
[BubbleResult a result] -- monotone list of results
bubbleSearch search p startOrder rs = bubble startOrder rs
where bubble order rs = BubbleResult answer answer rs : walk tries
where answer = search order
tries = perturbations p order rs
walk ((order, rs) : rest) =
if result > answer then bubble order rs
else BubbleResult answer result rs : walk rest
where result = search order
perturbations :: Double -> [a] -> [Double] -> [([a], [Double])]
perturbations p xs rs = xr' : perturbations p xs (snd xr')
where xr' = perturb xs rs
perturb :: [a] -> [Double] -> ([a], [Double])
perturb xs rs = shift_all p [] xs rs
shift_all p new' [] rs = (reverse new', rs)
shift_all p new' old rs = shift_one new' old rs (shift_all p)
where shift_one :: [a] -> [a] -> [Double] -> ([a]->[a]->[Double]->b) -> b
shift_one new' xs rs k = shift new' [] xs rs
where shift new' prev' [x] rs = k (x:new') (reverse prev') rs
shift new' prev' (x:xs) (r:rs)
| r <= p = k (x:new') (prev' `revApp` xs) rs
| otherwise = shift new' (x:prev') xs rs
revApp xs ys = foldl (flip (:)) ys xs
I'm sure this code looks like random gibberish. But if you read Mitzenmacher's blog entry and understand the algorithm, you'll be amazed that it's possible to package the algorithm into code without saying anything about what you're searching for.
我确定这段代码看起来像随意的乱码。但是,如果您阅读Mitzenmacher的博客条目并理解该算法,您会惊讶于可以将算法打包到代码中,而无需说明您要搜索的内容。
Having given you some examples as you asked for, I will say that the best way to start to appreciate Haskell is to read the paper that gave me the ideas I needed to write the DVD packer: Why Functional Programming Matters by John Hughes. The paper actually predates Haskell, but it brilliantly explains some of the ideas that make people like Haskell.
根据你的要求给了你一些例子,我会说开始欣赏Haskell的最好方法是阅读那些给我写DVD包装器所需要的想法的文章:为什么功能编程很重要John Hughes。这篇论文实际上早于Haskell,但它巧妙地解释了一些让人们喜欢Haskell的想法。
#12
For me, the attraction of Haskell is the promise of compiler guaranteed correctness. Even if it is for pure parts of the code.
对我来说,Haskell的吸引力在于编译器保证正确性的承诺。即使它是代码的纯部分。
I have written a lot of scientific simulation code, and have wondered so many times if there was a bug in my prior codes, which could invalidate a lot of current work.
我已经写了很多科学模拟代码,如果我之前的代码中存在一个错误,那么我已经多次想知道,这可能会使许多当前的工作无效。
#13
I find that for certain tasks I am incredibly productive with Haskell.
我发现对于某些任务,我使用Haskell非常高效。
The reason is because of the succinct syntax and the ease of testing.
原因在于简洁的语法和易于测试。
This is what the function declaration syntax is like:
这就是函数声明语法的含义:
foo a = a + 5
foo a = a + 5
That's is simplest way I can think of defining a function.
这是我能想到定义函数的最简单方法。
If I write the inverse
如果我写逆
inverseFoo a = a - 5
inverseFoo a = a - 5
I can check that it is an inverse for any random input by writing
我可以通过写入来检查它是否是任何随机输入的反转
prop_IsInverse :: Double -> Bool
prop_IsInverse a = a == (inverseFoo $ foo a)prop_IsInverse :: Double - > Bool prop_IsInverse a = a ==(inverseFoo $ foo a)
And calling from the command line
并从命令行调用
jonny@ubuntu: runhaskell quickCheck +names fooFileName.hs
jonny @ ubuntu:runhaskell quickCheck + names fooFileName.hs
Which will check that all the properties in my file are held, by randomly testing inputs a hundred times of so.
这将检查我的文件中的所有属性是否被保留,通过随机测试输入一百次。
I don't think Haskell is the perfect language for everything, but when it comes to writing little functions and testing, I haven't seen anything better. If your programming has a mathematical component this is very important.
我不认为Haskell是所有内容的完美语言,但是当谈到编写小函数和测试时,我还没有看到更好的东西。如果您的编程具有数学成分,则这非常重要。
#14
If you can wrap your head around the type system in Haskell I think that in itself is quite an accomplishment.
如果你可以在Haskell中绕过类型系统,我认为这本身就是一个很大的成就。
#15
it has no loop constructs. not many languages have this trait.
它没有循环结构。没有多少语言有这个特点。
#16
I agree with those that said that functional programming twists your brain into seeing programming from a different angle. I've only used it as a hobbyist, but I think it fundamentally changed the way I approach a problem. I don't think I would have been nearly as effective with LINQ without having been exposed to Haskell (and using generators and list comprehensions in Python).
我同意那些说功能编程能够让你的大脑从不同角度看编程的人。我只把它用作业余爱好者,但我认为它从根本上改变了我解决问题的方式。如果没有暴露给Haskell(并在Python中使用生成器和列表推导),我认为我对LINQ几乎没有那么有效。
#17
To air a contrarian view: Steve Yegge writes that Hindely-Milner languages lack the flexibility required to write good systems:
提出逆向观点:Steve Yegge写道,Hindely-Milner语言缺乏编写好系统所需的灵活性:
H-M is very pretty, in a totally useless formal mathematical sense. It handles a few computation constructs very nicely; the pattern matching dispatch found in Haskell, SML and OCaml is particularly handy. Unsurprisingly, it handles some other common and highly desirable constructs awkwardly at best, but they explain those scenarios away by saying that you're mistaken, you don't actually want them. You know, things like, oh, setting variables.
H-M非常漂亮,完全无用的正式数学意义。它很好地处理了一些计算结构;在Haskell,SML和OCaml中找到的模式匹配调度特别方便。不出所料,它充其量只是笨拙地处理其他一些常见且非常理想的结构,但是他们通过说你错了,你实际上并不想要它们来解释这些情况。你知道,哦,设置变量。
Haskell is worth learning, but it has its own weaknesses.
Haskell值得学习,但它有自己的弱点。