轻舟过
在研究Haskell的函数式编程

本帖最后由 轻舟过 于 2012-8-1 00:55 编辑

最近两天做了Haskell 99题中的前20道

函数式编程解决问题的思路还真是不一样

还有函数式编程是不是研究Lisp更好一点。。

题目链接在这里:http://www.haskell.org/haskellwiki/99_questions

相应的还有Prolog、Lisp、Perl、OCaml的99题

论坛的SyntaxHighlighter插件怎么没有Haskell的语法高亮

[mw_shl_code=text,true]-- #1

myLast :: [a] -> a

myLast (x:[]) = x

myLast (x:xs) = myLast xs

-- #2

myButLast :: [a] -> a

myButLast (x1:x2:[]) = x1

myButLast (x1:x2:xs) = myButLast (x2:xs)

-- #3

elementAt :: [a] -> Int -> a

elementAt (x:xs) 1 = x

elementAt (x:xs) idx = elementAt xs (idx - 1)

-- #4

myLength :: [a] -> Int

myLength xs = foldl (+) 0 $ map (\x -> 1) xs

-- #5

myReverse :: [a] -> [a]

myReverse = foldl (\xs x-> x:xs) []

-- #6

isPalindrome :: (Eq a) => [a] -> Bool

isPalindrome xs = xs == myReverse xs

data NestedList a = Elem a | List [NestedList a] deriving (Show)

-- #7

flatten :: NestedList a -> [a]

flatten (Elem x) = [x]

flatten (List lst) = foldl (++) [] $ map flatten lst

-- #8

compress :: (Eq a) => [a] -> [a]

compress [] = []

compress all@(x:xs) = (head $ takeWhile (==x) all):compress(dropWhile (==x) all)

-- #9

pack :: (Eq a) => [a] -> [[a]]

pack [] = []

pack all@(x:xs) = (takeWhile (==x) all):pack(dropWhile (==x) all)

-- #10

encode :: (Eq a) => [a] -> [(Int, a)]

encode [] = []

encode all@(x:xs) = ((myLength $ takeWhile (==x) all), x):encode(dropWhile (==x) all)

data RunLengthCode a = Single a | Multiple Int a deriving (Show)

-- #11

encodeModified :: (Eq a) => [a] -> [RunLengthCode a]

encodeModified [] = []

encodeModified lst = map toRunLengthCode $ encode lst

where toRunLengthCode pair = if fst pair == 1 then (Single (snd pair)) else (Multiple (fst pair) (snd pair))

-- #12

decodeModified :: [RunLengthCode a] -> [a]

decodeModified [] = []

decodeModified ((Single x):xs) = [x] ++ decodeModified(xs)

decodeModified ((Multiple len x):xs) = (replicate len x) ++ decodeModified(xs)

-- #13

encodeDirect :: (Eq a) => [a] -> [RunLengthCode a]

encodeDirect [] = []

encodeDirect all@(x:xs) = code:encodeDirect(dropWhile (==x) all)

where len = myLength $ takeWhile (==x) all

code = if len == 1 then (Single x) else (Multiple len x)

-- #14

dupli :: [a] -> [a]

dupli [] = []

dupli (x:xs) = [x, x] ++ dupli(xs)

-- #15

repli :: [a] -> Int -> [a]

repli [] _ = []

repli (x:xs) cnt = (replicate cnt x) ++ (repli xs cnt)

-- #16

{-

- dropEvery = flip $ \n -> map snd . filter ((n/=) . fst) . zip (cycle [1..n])

-}

dropEvery :: [a] -> Int -> [a]

dropEvery lst cnt = map snd $ filter (\p -> (fst p) `mod` cnt /= 0) $ zip [1..] lst

-- #17

split :: [a] -> Int -> ([a], [a])

split lst len = (take len lst, drop len lst)

-- #18

slice :: [a] -> Int -> Int -> [a]

slice lst start end = fst $ split (drop (start - 1) lst) (end - start + 1)

-- #19

rotate :: [a] -> Int -> [a]

rotate lst num = (drop len lst) ++ (take len lst)

where lstLen = length lst

len = (num `mod` lstLen + lstLen) `mod` lstLen

-- #20

removeAt :: Int -> [a] -> (a, [a])

removeAt num lst = (head lstTail, (take (num - 1) lst) ++ (tail lstTail))

where lstTail = drop (num - 1) lst

[/mw_shl_code]

然后还有spoj上的TEST

[mw_shl_code=text,true]main = do

line <- getLine

if line == "42"

then getContents

else do

putStrLn line

main[/mw_shl_code]

轻舟过
而且并行计算什么的函数式语言可以做的很好
展开Biu

ladace 发表于 2012-8-13 08:26

是啊……

而且并行计算什么的函数式语言可以做的很好,未来各种多核的话应该是函数式的天下。所以微软也 ...

因为函数式语言不会改变状态,没有副作用

[查看全文]
ladace
现在各种语言都有函数式编程的影子
展开Biu

轻舟过 发表于 2012-8-12 18:04

现在各种语言都有函数式编程的影子

像map、filter、reduce(haskell里叫foldX)什么的,像C++、Java什么 ...

是啊……

而且并行计算什么的函数式语言可以做的很好,未来各种多核的话应该是函数式的天下。所以微软也弄个F#什么的……

[查看全文]
轻舟过
函数式编程是未来的方向啊
展开Biu

ladace 发表于 2012-8-12 17:33

函数式编程是未来的方向啊……

现在各种语言都有函数式编程的影子

像map、filter、reduce(haskell里叫foldX)什么的,像C++、Java什么的都要引入lambda

[查看全文]
ladace
本帖最后由
展开Biu

本帖最后由 ladace 于 2012-8-12 17:34 编辑

轻舟过 发表于 2012-8-11 15:43

定义是说使语法更容易表达和理解的东西叫语法糖

然后看到C里面的a[ i ]也是语法糖,用来代替比较难看的*( ...

函数式编程是未来的方向啊……

[查看全文]
轻舟过
少写括号感觉很爽啊
展开Biu

ladace 发表于 2012-8-11 15:34

$少写括号感觉很爽啊……

刚才查了一下维基……好像对语法糖理解有误……(5+)这种也是语法糖吧……

定义是说使语法更容易表达和理解的东西叫语法糖

然后看到C里面的a[ i ]也是语法糖,用来代替比较难看的*(a+i)

表示我是像学一下函数式编程才去学haskell的,然后感觉真是精妙

[查看全文]
ladace
刚刚发现对函数进行
展开Biu

轻舟过 发表于 2012-8-11 14:49

刚刚发现对函数进行fmap实际上就是 . 的效果,好神奇

像$感觉就是用来少写几个括号的?

$少写括号感觉很爽啊……

刚才查了一下维基……好像对语法糖理解有误……(5+)这种也是语法糖吧……

我也是新手来着……最近在家学英语,把Haskell的学习搁置了……

看了Write Yourself a Scheme in 48 Hours大半部分,再配合点别的……觉得把解释器都写出来了写点啥应该不成问题了吧……打算有点代码经验了回头再看那些比较系统比较细的教程,不然也记不住……

[查看全文]
轻舟过
的标点符号可以引入很多语法糖
展开Biu

ladace 发表于 2012-8-11 09:44

Haskell的标点符号可以引入很多语法糖…… . 和 $ 这种都算吧……

然后还有Control.Arrow库里有一坨奇怪 ...

刚刚发现对函数进行fmap实际上就是 . 的效果,好神奇

像$感觉就是用来少写几个括号的?

参数模式匹配确实很爽啊,像C语言写类似的东西时候都是写if什么什么的,感觉haskell是把不同情况下的代码完全分离开了

像(5+)这种部分参数绑定的也很神奇的

Haskell的自动类型推断好强大

最后你有什么关于Haskell的资料可以推荐的吗,像书、网站、练习题什么的都可以。

目前在看的是《Learn you a Haskell for Great Good!》

[查看全文]
ladace
我也了解不多啦
展开Biu

轻舟过 发表于 2012-8-10 22:54

其实lisp我也了解不多啦,所以可以无视上面我所说的

haskell其实也才看了一点,还不太了解Monad

lisp的有 ...

Haskell的标点符号可以引入很多语法糖…… . 和 $ 这种都算吧……

然后还有Control.Arrow库里有一坨奇怪的标点符号……跟Monad相关的,还没研究……

其它有啥我忘了……

其实我觉得像 (5+) 这种写法 和 参数模式匹配也很爽的……不过貌似不能叫语法糖……

感觉Haskell在语法上面做了不少功夫,让人写程序很舒服……我现在就觉得一个舒服的语言就可以自然的让人写出总分结构的代码来。觉得命令式语言在一个局部都是分总的感觉,先要思考用到哪些变量,然后再去做实际的事,如果以总分的思维来写光标就要跳来跳去;另外一个——感觉C的类型转换的语法也很让人不爽,因为按照正常思维都是先去想变量的名字再去思考是否做类型转换,所以感觉语法应该设定成类型出现在变量后面,这样就非常顺畅。这就是我关于语言的想法。于是发现Haskell在这一点做的不错……一切都是惰性求值所赐……虽然最后结论需要用它写点大工程才能得到……

说得有点乱…………

[查看全文]