learn-haskell
时间:2022-05-30
本文章向大家介绍learn-haskell,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
引言
Haskell不同于Scala,是一门纯函数式语言,它强制使用者使用函数式语法而没有妥协。
- 是一门强类型定义的静态类型语言。它的**类型模型基于推断理论(in-ferred)**并被公认为是函数语言中最高效的类型系统之一。你会发现该类型系统支持多态语义并有助于人们作出十分整洁清晰的设计。
- 支持Erlang风格的模式匹配(pattern matching)和哨兵表达式。你也能在Haskell中发现Clojure风格的惰性求值(lazyevaluation)以及与Clojure和Erlang相同的列表推导语法。
- 无副作用,通过monad概念保存状态:一个Haskell函数可以返回一个有副作用并且会被延迟执行的结果.
Day1 逻辑
在OS X下安装Haskell环境:brew install haskell-platform
通过命令启动交互式环境:ghci
基本类型
{- basic type -}
Prelude> 4 * (5 + 1)
24
Prelude> "hello" ++ " world"
"hello world"
Prelude> ['a', 'b'] --list
"ab"
['a', 'b'] :: [Char]
Prelude> (1,2,3) --tuple
(1,2,3) :: (Num t, Num t1, Num t2) => (t, t1, t2)
Prelude> if (5 == 5) then "true" else "false""true"
"true"
{- var accessing -}
fst tuple
snd tuple
head list
last list
tail list
let (h:t) = [1, 2, 3, 4] {- h=1, t=[2,3,4] -}
1:[2,3,4] {- [1,2,3,4] -}
{- verbose type info -}
Prelude> :set +t
Prelude> :t 2
2 :: Num a => a
Prelude> (5 == (2 + 3))
True
it :: Bool
D2 函数
定义
{- let binding -}
Prelude> let x = 10
x :: Integer
Prelude> let double x = x * 2
double :: Num a => a -> a
{- dot notation -}
Prelude> let second = f . g
Prelude> let second list = f (g list)
second :: [a] -> a
{- ./double.hs -}
module Main where
{- without type def -}
double x = x + x
{- with type def -}
double_int :: Integer -> Integer
double_int x = x + x
{- load .hs in GHCi -}
*Main> :load double.hs
*Main> double 2
4
递归
Prelude> let fact x = if x == 0 then 1 else fact (x - 1) * x
{- ./fact_with_guards.hs -}
module Main where
fact :: Integer -> Integer
fact x
| x > 1 = x * fact(x - 1) {- sentinel -}
| otherwise = 1
使用Tuple
{- ./fib_recusive.hs -}
module Main where
fib :: Integer -> Integer
fib 0 = 1
fib 1 = 1
fib x = fib(x - 1) + fib(x - 2)
{- ./fib_tuple.hs -}
module Main where
fibFast :: Integer -> Integer
fibFast x = fibResult(fibTuple(0,1,x))
fibTuple :: (Integer, Integer, Integer) -> (Integer, Integer, Integer)
fibTuple (x, y, 0) = (x, y, 0)
fibTuple (x, y, index) = fibTuple (y, x + y, index - 1)
fibResult :: (Integer, Integer, Integer) -> Integer
fibResult (x,y,z) = x
{- ./fib_pair.hs -}
module Main where
{- using Tuple-}
fibFast :: Integer -> Integer
fibFast = fst . fibNthPair
fibNextPair :: (Integer, Integer) -> (Integer, Integer)
fibNextPair (x, y) = fibNextPair (y, x + y)
fibNthPair :: Integer -> (Integer, Integer)
fibNthPair 1 = (1,1)
fibNthPair x = fibNextPair(fibNthPair(x-1))
遍历列表
通过let (h:t) = list
{- ./fib_pair.hs -}
module Main where
size [] = 0
size (h:t) = 1 + size (t)
prod [] = 1
prod (h:t) = h * prod (t)
生成列表
1:[2,3,4] -> [1,2,3,4]
偶数列表
module Main where
allEven :: [Integer] -> [Integer]
allEven [] = []
allEven (h:t) = if even h then h:allEven t else allEven t
Range
[1..10]
[10, 8 .. 4]
take 5 [0, 2 ..]
List Derivation (like python)
[x * 2 | x <- [1,2,3]]
[(y,x+1) | (x,y) <-[(1,2),(2,3),(3,4)]]
let crew = ["Spock", "Kirk", "McCoy"]
[(a,b) | a <- crew, b <- crew, a/=b] {- /= means not equal -}
练习 乘法表
module Main where
mulTable :: Integer -> [(Integer,Integer,Integer)]
mulTable 1 = mulTableRow 1
mulTable n = (mulTableRow n) ++ (mulTable (n-1))
mulTableRow :: Integer -> [(Integer,Integer,Integer)]
mulTableRow n = [(x,y,x*y) | x <- [n], y<-[1..n]]
{-
*Main> mulTable 2
[(2,1,2),(2,2,4),(1,1,1)]
-}
Day2
高阶函数
匿名函数
(param1.. paramn ->function_body)
map
map (x -> x * x) [1, 2, 3]
filter、foldl和foldr (reduce)
Prelude> filter odd [1, 2, 3, 4, 5]
[1,3,5]
Prelude> foldl (x carryOver -> carryOver + x) 0 [1 .. 10]
55
Prelude> foldl1 (+) [1 .. 3]
6
where
{- haskell/map.hsmodule -}
module Main where
squareAllPlusOne list = map squarePlusOne list
where
squarePlusOne x = x * x + a
let a = 1
柯里化
把多参数函数,拆分成多个只有一个参数的函数
Prelude> double x = x * x
double :: Num a => a -> a
Prelude> let prod x y = x * y
prod :: Num a => a -> a -> a
Prelude> let double = prod 2
double :: Integer -> Integer
惰性求值
一个无尽序列
{- my_range.hs -}
module Main where
myRange start step = start:(myRange (start + step) step)
惰性 Fib 数列
{- lazy_fib.hs -}
module Main where
lazyFib x y = x:(lazyFib y (x + y))
fib = lazyFib 1 1
fibNth x = head (drop (x - 1) (take (x) fib))
Day3
类与类型
自定义类型
{- cards.hs -}
module Main where
data Suit = Spades | Hearts deriving (Show)
data Rank = Ten | Jack | Queen | King | Ace deriving (Show)
type Card = (Rank, Suit)
type Hand = [Card]
value :: Rank -> Integer
value Ten = 1
value Jack = 2
value Queen = 3
value King = 4
value Ace = 5
cardValue :: Card -> Integer
cardValue (rank, suit) = value rank
--
*Main> cardValue (Ten, Hearts)
1
多态函数
backwards :: [a] -> [a]
backwards [] = []
backwards (h:t) = backwards t ++ [h]
多态数据类型
类型相同的三元组、
module Main where
data Triplet a = Trio a a a deriving (Show)
--
*Main> :t Trio
Trio :: a -> a -> a -> Triplet a
树
module Main where
data Tree a = Children [Tree a] | Leaf a deriving (Show)
-- 计算高度 --
depth (Leaf _) = 1
depth (Children c) = 1 + maximum (map depth c)
--
*Main> let leaf1 = Leaf 11
*Main> let leaf2 = Leaf 22
*Main> let tree = Children[Leaf 1, Leaf 2]
*Main> tree
Children [Leaf 1,Leaf 2]
类
非面向对象的类概念,它不涉及数据,可以精细控制重载和多态。
以下是 Eq 类的定义:
class Eq a where
(==), (/=) :: a -> a -> Bool
-- Minimal complete definition:
-- (==) or (/=)
x /= y = not (x == y)
x == y = not (x /= y)
类支持继承:
Monad
海盗寻宝问题
Python Approach
def treasure_map(v):
v = stagger(v)
v = stagger(v)
v = crawl(v)
return v
Functional Approach
module Main where
stagger :: (Num t) => t -> t
stagger d = d + 2
crawl d = d + 1
treasureMap d =
crawl (stagger (stagger d))
Let-in Approach
module Main where
letTreasureMap (v,d) =
let d1 = stagger d
d2 = stagger d1
d3 = crawl d2
in d3
Monad Approach
module Main where
data Position t = Position t deriving (Show)
stagger (Position d) = Position (d + 2)
crawl (Position d) = Position (d + 2)
rtn x = x -- packaging monad
x >>== f = f x -- bind
treasureMap pos = pos >>==
stagger >>==
stagger >>==
crawl >>==
rtn
--
*Main> treasureMap (Position 0)
5
More Monad
do Sugar Syntax
module Main where
tryIo = do
putStr "Enter your name: " ;
line <- getLine ;
let { backwards = reverse line} ;
return ("Hello. Your backwards is " ++ backwards)
Definitions of return and bind(>>==)
instance Monad [] where
m >>= f = concatMap f m
return x = [x]
Crack Password
module Main where
crack = do
x <- ['a'..'c']; y <- ['a'..'c']; z <- ['a'..'c'];
let {password = [x,y,z]};
if attempt password
then return (password, True)
else return (password, False)
attempt pw = if pw == "cab" then True else False
Maybe Monad
Maybe 能够解决一些函数返回失败,如数据库、网络、文件I/O等函数。
下面是 Just 定义:
{- Just 类似 Swift 的 Optional-}
Prelude> Just "some string"
Just "some string"
Prelude> Just Nothing
Just Nothing
Prelude> :t Just
Just :: a -> Maybe a
Prelude> :t Nothing
Nothing :: Maybe a
{- Def. of HTML handler -}
paragraph xmlDoc -> xmlDoc
body xmlDoc -> xmlDoc
html xmlDoc -> xmlDoc
进入正题,处理HTML文档,不用 Maybe Monad 时需要处理每层(paragraph / html / body)的 Nothing 异常:
用 Maybe Monad :
{- Without Maybe Usage-}
paragraph body (html xmldoc)
{- Without Maybe Implementation (trival in handling exception)-}
case (html doc) of
Nothing -> Nothing
Just x -> case body x of
Nothing -> Nothing
Just y -> paragraph 2 y
用 Maybe Monad :
{- Maybe Usage-}
Just someWebPage >>== html >>= body >>== paragraph >>== return
{- Def. of Maybe Monad -}
data Maybe a = Nothing | Just a
instance Monad Maybe where
return = Just
Nothing >>= f = Nothing
(Just x) >>= f = f x
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Python类及获取对象属性方法解析
- Keras实现DenseNet结构操作
- python中format函数如何使用
- keras得到每层的系数方式
- 解决TensorFlow调用Keras库函数存在的问题
- php判断电子邮件是否正确方法
- python db类用法说明
- python中wheel的用法整理
- 使用Keras训练好的.h5模型来测试一个实例
- python中查看.db文件中表格的名字及表格中的字段操作
- Ubuntu 16.04中Laravel5.4升级到5.6的步骤
- PHP SESSION机制的理解与实例
- Yii支持多域名cors原理的实现
- PHP实现的pdo连接数据库并插入数据功能简单示例
- php基于Redis消息队列实现的消息推送的方法