-- 经典的菲波纳契数列的函数定义,求每一个位置上的数值
fib 1 = 1
fib 2 = 1
fib n = fib(n-1) + fib(n-2)
-- 产生一个无限长的fib数列
fib_l n = fib n : fib_l (n+1)
take 10 (fib_l 1) => [1,1,2,3,5,8,13,21,34,55]
--另一个更快解法
fibs = fibgen 1 1
fibgen n1 n2 = n1 : fibgen n2 (n1+n2)
--求解素数的一个无限数列方法:
prime = sieve [2..]
sieve (x:xs) = x : sieve (filter (\y ->y `rem` x /= 0) xs)
take 25 prime => [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97]
--打印头 100 个汉明数(以2、3、5 的阶乘为因子的正整数)
main = print (take 100 hamming)
hamming = 1 : (map (2*) hamming) ~~ (map (3*) hamming) ~~ (map (5*) hamming)
where
xxs@(x:xs) ~~ yys@(y:ys)
| x==y = (x : xs~~ys)
| x<y = x:xs~~yys
| otherwise = (y : xxs~~ys)
--克拉兹(Collatz)问题
module Main where
import Data.Tuple
import Data.List (sortBy)
import Data.Function (on)
chain' :: Integer -> [Integer]
chain' 1 = [1]
chain' n
| n <= 0 = []
| even n = n : chain' (n `div` 2)
| odd n = n : chain' (n * 3 + 1)
main :: IO ()
main = do
let seqx = map (\x -> (x, length $ chain' x)) [999999,999997..3]
print . fst .head $ sortBy (flip compare `on` snd) seqx
--更快的解法
module Main where
import Data.Tuple
import Data.List (sortBy, iterate)
import Data.Function (on)
chain' :: Integer -> Int
chain' n
| n < 1 = 0
| otherwise = 1 + (length $ (takeWhile (> 1) $ iterate (\x ->if even x then x `div` 2 else x * 3 + 1) n))
main :: IO ()
main = do
let seqx = map (\x -> (x, chain' x)) [999999,999997..3]
print . fst .head $ sortBy (flip compare `on` snd) seqx
--对可变(mutable)变量的读写
incRef :: IORef Int -> IO ( )
import Data.List
import Data.Function
type Key = String
type Score = Int
data Thing = Thing {key :: Key, score :: Score } deriving (Show)
myNub = nubBy ((==) `on` key)
mySort = sortBy (compare `on` (negate .score))
selectFinest = myNub . mySort
在ghci中测试:
Prelude> :load Test.hs
*Main> selectFinest [Thing "a" 7, Thing "b" 5, Thing "a" 10]
[Thing {key = "a", score = 10},Thing {key = "b", score = 5}]
--解码 X509 文件
import Data.ByteString (ByteString) import Data.Certificate.PEM import Data.Certificate.X509 import qualified Data.ByteString as B import qualified Data.ByteString.Lazy as L decode :: ByteString -> Either String X509 decode pem = case parsePEMCert pem of Nothing -> Left "certificate not in PEM format" Just certdata -> decodeCertificate $ L.fromChunks [certdata] main :: IO () main = print . decode =<< B.readFile "ca-cert.pem"
--As an example of using the ST
monad with mutable arrays, here is an implementation of the Sieve of Erathostenes:
import Control.Monad.ST import Data.Array.ST import Data.Array.Unboxed primesUpto :: Int -> [Int] primesUpto n = [p | (p, True) <- assocs $ sieve n] sieve :: Int -> UArray Int Bool sieve n = runSTUArray $ do sieve <- newArray (2, n) True forM_ [2..n] $ \p -> do isPrime <- readArray sieve p when isPrime $ do forM_ [p*2, p*3 .. n] $ \k -> do writeArray sieve k False return sieve --让用户输入很多行, 以空行结束 .递归实现 import Prelude hiding (readList) import Control.Applicative import Control.Monad import Control.Monad.Trans import Control.Monad.Trans.Maybe import Data.Maybe readList :: IO [String] readList = do l <- getLine if null l then return [] else (l :) <$> readList .非递归实现 通用的many组合子可用于任何applicative函子 many :: Applicative f => f a -> f [a] IO函子不是Applicative的实例, 但我们可以在其上面加一层MaybeT transformer来解决此问题。MaybeT将是我们区别成功/失败的方法。 readList :: IO [String] readList = fmap (fromMaybe []) $ runMaybeT $ many $ do l <- lift getLine guard $ not $ null l return l .lift getLine以MaybeT的角度(总是成功)将getLine从IO String提升(lift)至MaybeT IO String .guard是MonadZero类的函数,用于检查条件是否有效。它与assert函数相似,但它用于流程控制而不是调试 .如果guard没有放弃计算,将简单返回刚读入的行
--runSTUArray
is a specialized form ofrunST
which allows you to build an array using mutation on the inside, --before freezing it and returning it as an immutable array.newArray
,readArray
andwriteArray
do what you'd expect.