轻舟过
在研究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]

Richeir
前原圭一
展开Biu

前原圭一 发表于 2012-8-1 16:07

对于会ruby的人来说,python实在是

@22#

Python是啥,能吃么...我不知道唉...

[查看全文]
轻舟过
前原圭一
展开Biu

前原圭一 发表于 2012-8-1 16:06

Lisp中倒是可以用let之类的来保存中间变量

haskell我没学太多,不知道有没有类似的东西 ...

haskell也有let的

我的程序里用到了where,也是差不多的东西

[查看全文]
前原圭一
我们是介绍新手入门
展开Biu

Richeir 发表于 2012-8-1 15:54

我们是介绍新手入门...

@3*对于会ruby的人来说,python实在是

[查看全文]
前原圭一
中间结果应该是可以保存的
展开Biu

轻舟过 发表于 2012-8-1 14:48

中间结果应该是可以保存的

尾递归不知道有没有优化,有些操作倒是可以用函数如map、filter之类的

map、fi ...

@29*Lisp中倒是可以用let之类的来保存中间变量

haskell我没学太多,不知道有没有类似的东西

[查看全文]
Richeir
差不多啊
展开Biu

秋声赋 发表于 2012-8-1 15:11

.....

Ruby和Python差不多啊

没必要重复学

@17#

我们是介绍新手入门...

[查看全文]
秋声赋
给大神跪了
展开Biu

Richeir 发表于 2012-8-1 13:55

给大神跪了,我们写教程贴是面向那些想入门的人,或者想学习这门语言的人~~

阁下技能树点了好几层 ...

.....

Ruby和Python差不多啊

没必要重复学

既然学了Ruby就要会用

我记得RPGMaker的脚本就是用的Ruby

可以和游戏制作板块那边联动一下

[查看全文]
轻舟过
前原圭一
展开Biu

前原圭一 发表于 2012-8-1 14:23

嗯其实也就是觉得性能上有问题

如果流程中的每一个部分都要从最初的输入开始进行处理的话,应该会有 ...

中间结果应该是可以保存的

尾递归不知道有没有优化,有些操作倒是可以用函数如map、filter之类的

map、filter什么的现在好多语言都有

[查看全文]
前原圭一
函数式的优点是没有状态
展开Biu

轻舟过 发表于 2012-8-1 14:19

函数式的优点是没有状态,给函数同样的输入,它能保证给出同样的输出

其实现在很多编程语言都借鉴了函数 ...

@18*嗯其实也就是觉得性能上有问题

如果流程中的每一个部分都要从最初的输入开始进行处理的话,应该会有很多重复操作

尾递归的话不知道haskell有没有做优化

[查看全文]