为他人惠
最近业余在翻译一篇教程“Understanding Haskell Monads”,取得了原作者的同意后准备将其译为中文,现在是用xelatex排版的,放在了github里。对于没有TeX环境的同学,可以直接阅读生成的PDF文档(会不定期更新)。
本人对于翻译没有什么经验,特别是对于一些专业术语,踟蹰良久,自己重读的时候有些地方也感觉多少有点拗口。如果有表达不清楚或者不准确的地方,欢迎拍砖。
Let only that little be left of me whereby I may name thee my all.
最近业余在翻译一篇教程“Understanding Haskell Monads”,取得了原作者的同意后准备将其译为中文,现在是用xelatex排版的,放在了github里。对于没有TeX环境的同学,可以直接阅读生成的PDF文档(会不定期更新)。
本人对于翻译没有什么经验,特别是对于一些专业术语,踟蹰良久,自己重读的时候有些地方也感觉多少有点拗口。如果有表达不清楚或者不准确的地方,欢迎拍砖。
做了Google Code Jam 2010的Qualification Round的三道题,开始都是用 Haskell 写的,第三道在处理大数据集时总是堆栈溢出,无奈之下改用了 Python,修改了一下算法,加入一个哈希表,避免重复运算,果然一下就搞定了。心里有了底之后修改了 Haskell 程序里面的代码,也加入一个 IntMap,也搞定了。
标签: haskell, programming
Scala 里有个叫做 "case classes" 的东西,这个应该是从 ML 家族的语言特性启发而来,习惯于 C/C++ 的程序员可能较少看到这个名词。比如,我们要写一个算术表达式解析器,比如下面就是一些合法的表达式:
> data Expr =
> Number Int
> | Var String
> | UnOp String Expr
> | BinOp String Expr Expr
> deriving (Show)
abstract class Expr
case class Var(name: String) extends Expr
case class Number(num: Double) extends Expr
case class UnOp(operator: String, arg: Expr) extends Expr
case class BinOp(operator: String, left: Expr, right: Expr) extends Expr
scala> val op = BinOp("+", Number(1), Var("x"))
op: BinOp = BinOp(+,Number(1.0),Var(x))ghci> let op = BinOp "+" (Number 1) (Var "x")
ghci> op
BinOp "+" (Number 1) (Var "x")
"Programming in Haskell" 的第十一章讲的是countdown problem,就是说给定一系列操作,比如加减乘除,和一系列自然数,比如2,5,9,17,求出可能的组合方法使得表达式的结果为给定数值,比如24。在这个简单的例子中,我们找到两种解法:
标签: haskell
周末看了一篇"The Evolution of a Haskell Programmer",里面列举了Haskell程序员写阶乘函数fac的各种实现方法,可以用两个成语来形容:琳琅满目、叹为观止。虽然感觉上有点类似孔乙己在纠缠茴香豆的茴字有几种写法,不过内容还真的挺有意思。其中有两个实现方法可以稍微聊一聊:1. CPS;2.利用Y combinator。
标签: haskell
源代码来自:http://www.cs.nott.ac.uk/~gmh/compiler.lhs
> data Expr = Val Int | Add Expr Expr
>
> eval :: Expr -> Int
> eval (Val n) = n
> eval (Add x y) = eval x + eval y
>
> type Stack = [Int]
>
> type Code = [Op]
>
> data Op = PUSH Int | ADD
>
> exec :: Code -> Stack -> Stack
> exec [] s = s
> exec (PUSH n : c) s = exec c (n:s)
> exec (ADD : c) (m:n:s) = exec c (n+m:s)
>
> comp' :: Expr -> Code -> Code
> comp' (Val n) c = PUSH n : c
> comp' (Add x y) c = comp' x (comp' y (ADD : c))
>
> comp :: Expr -> Code
> comp e = comp' e []
*Main> let e = Add (Val 1) (Val 2)
*Main> exec (comp e) []
[3]
标签: haskell
第七课的小练习:http://www.cs.nott.ac.uk/~gmh/chapter7.ppt
标签: haskell
本想自力更生试着用Haskell写个JSON解析器,一不小心网上一搜一大把,并且忍不住瞄了几眼。那就做个简单的修改加翻译吧,原文链接:http://snippets.dzone.com/posts/show/3660
> import Text.ParserCombinators.Parsec
> import System
> import qualified Data.Map as Map
> mainParser = do {
> val <- valueParser
> ; skipMany space
> ; eof
> ; return val
> }
> main :: IO ()
> main = do {
> args <- getArgs
> ; val <- parseFromFile mainParser $ args !! 0
> ; print val
> }
> data JSON = ListValue [JSON]
> | LiteralString String
> | LiteralInt Integer
> | LiteralBoolean Bool
> | RecordValue (Map.Map String JSON)
> deriving Show
LiteralString "abc"
LiteralInt 123
:t LiteralString "abc"
LiteralString "abc" :: JSON
> literalString :: Parser JSON
> literalString = do {
> char '"'
> ; val <- many1 letter
> ; char '"'
> ; return $ LiteralString val
> }
> literalInt :: Parser JSON
> literalInt = do {
> ; val <- many1 digit
> ; return $ LiteralInt (read val)
> }
> valueParser :: Parser JSON
> valueParser =
> literalString
> <|> literalInt
> <|> literalBoolean
> <|> recordParser
> <|> listParser
> listParser :: Parser JSON
> listParser = do {
> char '['
> ; words <- sepBy1 valueParser listSeparator
> ; char ']'
> ; return $ ListValue words
> }
> recordParser :: Parser JSON
> recordParser = do {
> char '{'
> ; defs <- endBy definitionParser listSeparator
> ; char '}'
> ; return $ RecordValue $ Map.fromList defs
> }标签: haskell
曾经立志成为Linux内核高手,并为此努力研究了几年,后来无论是实习、还是现在的第一份工作都与此有所背离,于是就希望在compiler方面有所建树 -- 想要成为一个有功力、有底气的非内核程序员,这个应该是一个有意义的方向。于是就先读了SICP(当然其中还有老大的影响),学了Scheme -- 记得当时在某个邮件列表上看见说Scheme很适合用来模拟别的语言。读SICP还是相当令人愉悦的,从中学到了很多有益的思想并有了一点函数式编程思维。
标签: haskell, programming
前一篇文章中缺乏示例,一眼看下去可能不太好理解。这次用几个简单的例子说明一下。
int add(int x, int y) { return x + y; }
static int count = 0;
int add(int x, int y) { count++; return x + y; }
add x y = x + y
add x y cnt = (x + y, cnt + 1)标签: haskell
在函数式编程领域有所谓Pure和Impure之分。简单来说,两者之间的区别就是Impure是有side-effect的,比如:赋值、异常和continuations;而Pure则意味着对于一个函数来说相同的输入一定会产生相同的输出,函数中也没有赋值操作这些用以改变某个状态的行为。Scheme和Standard ML是Impure的,而Miranda和Haskell则选择了Pure。
标签: haskell
Dr. Erik Meijer 在MSDN Channel9上开设了Functional Programming Fundamentals,总共13次课,目前已经完成4课视频,并有各种格式可供免费下载。想了解函数式编程的同学不妨移步一观,课程基于Haskell,内容流畅且富有洞察,一定会有所获。
标签: haskell
这几天在看Philip Wadler的名篇Monads for functional programming,三十页出头,挺享受。看着看着,不由自主的想到Scheme里面的continuation,总觉得它们两者之间本质上有某种相通之处,却因尚未深入理解所以无法言语 -- 一种奇怪的感觉。那个共通之处是什么呢?lambda,也就是函数。
标签: haskell
今天在learnyouahaskell.com上看见一段逆波兰表达式计算器的代码,挺美妙的。
solveRPN :: (Num a, Read a) => String -> a
solveRPN = head . foldl foldingFunction [] . words
where foldingFunction (x:y:ys) "*" = (x * y):ys
foldingFunction (x:y:ys) "+" = (x + y):ys
foldingFunction (x:y:ys) "-" = (y - x):ys
foldingFunction xs numberString = read numberString:xs
标签: haskell
-- compile with: ghc --make cat.hs
import System.IO
import System.IO.Error
import System.Environment
cat :: String -> IO ()
cat fn = do
contents <- readFile fn
putStr contents
handler :: IOError -> IO ()
handler e
| isDoesNotExistError e =
case ioeGetFileName e of
Just path -> putStrLn $ path ++ ": file not found"
Nothing -> putStrLn "Oops! File unknown."
| otherwise = ioError e
main = do args <- getArgs
if null args
then interact id
else mapM_ (\fn -> cat fn `catch` handler) args
标签: haskell
每学一门语言首先想做的是用它写一个类UNIX下cat命令的东西,简单但至少涉及命令行处理和文件I/O。
(define (cat . arg)
(let ((port (if (null? arg)
(current-input-port)
(car arg))))
(let loop ((c (read-char port)))
(if (not (eof-object? c))
(begin
(display c)
(loop (read-char port)))))))
(define (main args)
(if (null? (cdr args))
(cat)
(for-each (lambda (port) (cat port) (close-input-port port))
(map open-input-file (cdr args)))))
import System.Environment
cat :: String -> IO ()
cat fn = do
contents <- readFile fn
putStr contents
main = do args <- getArgs
if null args then interact id else mapM_ cat args
import qualified Data.ByteString.Lazy as B
cat :: String -> IO ()
cat fn = do
bs <- B.readFile fn
B.putStr bs
我现在的状态大概可以用“带薪学习”来形容 -- 但老实说,这种状态下的学习效率多数都很低下。
标签: haskell
Haskell是一门纯函数式语言。不同于C/C++等语言的是,函数式语言中的函数乃是语言中的一等公民,它们本身也可以作为函数参数或者返回值,就像整型、字符串一样。几乎所有函数式语言的教程中,第一个示例函数都是求阶乘。在Haskell中:
fac 0 = 1
fac n = n * fac(n-1)
Prelude> :load "fac.hs"
[1 of 1] Compiling Main ( fac.hs, interpreted )
Ok, modules loaded: Main.
*Main> fac 4
24
*Main> fac 40
815915283247897734345611269596115894272000000000
add x y = x + y
*Main> add 1 2
3
*Main> let add2 = add 2
*Main> add2 3
5
Prelude> map (negate . abs) [5,-3,-6,7,-3,2,-19,24]
[-5,-3,-6,-7,-3,-2,-19,-24] 标签: haskell