函数式语言学院派之haskell之一

来源:互联网 发布:北京学软件测试 编辑:程序博客网 时间:2024/06/06 17:12

学院派系列全部都是我半年上的一节课上的作业。包含了haskell,ocaml,prolog,curry,scheme。极有意思。

二话不说,先贴一些代码,边看边说。

最初的作业,比较简单,翻翻基本的书就行。

module Manysort   ( insSort

,quickSort
,selectionSort
, mergeSort
) where


--insSort
insert :: (Ord a) => a ->[a] -> [a]
insert x [] = [x]
insert x (y:ys)
| x <= y = (x:y:ys)
| otherwise = y:(insert x ys)
insSort :: (Ord a) => [a] -> [a]
insSort [] =[]
insSort (x:xs) = insert x (insSort xs)


-- quickSort
quickSort :: (Ord a) => [a] -> [a]   
quickSort [] = []   
quickSort (x:xs) =   
  let small = quickSort [a | a <- xs, a <= x]  
      big = quickSort [a | a <- xs, a > x]   
  in small ++ [x] ++ big


-- selectionSort
selectionSort :: (Ord a) => [a] -> [a]
selectionSort [] = []
selectionSort xs = let x = minimum xs in x : selectionSort (remove x xs) 
  where remove _ [] = []
        remove a (x:xs)
          | x == a = xs
          | otherwise = x : remove a xs




--mergeSort
split :: [a] -> ([a],[a])
split xs = go xs xs where
go (x:xs) (_:_:zs) = (x:us,vs) where (us,vs)=go xs zs
go    xs   _       = ([],xs)
merge :: (Ord a)=> [a] -> [a] -> [a]
merge  xs []         = xs
merge  [] ys         = ys
merge  (x:xs) (y:ys)
     |  x <= y = x: merge  xs (y:ys)
     | otherwise = y: merge  (x:xs) ys
 
mergeSort :: (Ord a)=> [a] -> [a]
mergeSort  []   = []
mergeSort  [x]  = [x]
mergeSort  xs = merge  (mergeSort  xs1) (mergeSort  xs2)
   where

        (xs1,xs2) = split xs

和名字一样,最初的作业仅仅是让我们写写排序熟悉熟悉下语法罢了。

有几个比较有意思的地方。

1 haskell支持类型推论。所以开头可写类型可不写,主要是为了人看。

2  (Ord a)啥的不能少,它没有权限的事(Ord比较,show显示,...)不能做

3 partten matching 还是比较聪明的,进了上面的partten就不会进下面的任何一个。

4 空格不空格对其不对齐意思差别很大,千万注意着对齐写。也因为这个,导致代码看上去比较整洁。

5 go where 式的语法貌似是haskell的标准写法。


import Control.Monad
import Control.Monad.Instances 


ones = 1: [x | x <- ones]
nats = 1: [x + 1 |x <- nats]
fibs =  1:1:zipWith (+) fibs (tail fibs)
isPrime=ap(all.((0/=).).mod)$flip takeWhile primes.(.join(*)).flip(<=) 
primes=2:filter isPrime[3,5..] 

第二个小作业

它告诉了我们,因为haskell是延迟评价语言,所以完美的支持无限list。

基本不用说啥了吧


import Data.List
repeat_ x = x : repeat_ x
downto n =  n: downto (n-1)
firstlist_ n =  (take (n-1) (repeat_ n)) ++ (take n (downto n ))
lastlist_ n = ((take n (downto n ) ++ take (n-1) (repeat_ n)) )
firstlist =concat(map firstlist_ [0..])
lastlist =concat(map lastlist_ [0..])
natPairs=zip firstlist lastlist

实现了无限自然数对。看看不多,刚学的时候想的话还是要点时间的。但我写的不好,因为不能让读的人一下子看出来在干什么。这对于函数式语言就称不上好。

好的函数式编程应该是以易懂的代码精练地实现高级的任务。


memoize f = let rs = map f [0..] in (rs !!)
mfib = memoize 
(\x -> if x <= 2 then 1 
else mfib (x-1) + mfib (x-2))

这是个好东西,比一般的fib要快。

请大家想想为什么吧!

现在已经触碰到函数式语言比较坑爹的地方了。

你可以想机器说明你想干什么,你却一般不可以很细地去微调它怎么做。

这里就体现出了coder的智慧。

写函数式语言一定要用末尾递归,

同时记得haskell是延迟评价。


其实按顺序应该sheme,ocaml之后再haskell的,不过不用在意这个细节。


0 0
原创粉丝点击