您的位置:首页 > 其它

haskell学习笔记(8)-haskell的类型系统

2017-12-28 09:51 459 查看

类型推导

haskell因为支持类型推导,所以大多数时候不用显式写出类型声明,但是如果要写库的话,最好是写上类型声明,可以当做文档使用,看上去一目了然。

haskell的类型推导比大部分语言要强不少,例如和同样有类型推导的kotlin相比,kotlin并不支持传入参数的自动推导

例如

//a b参数都要写明类型
fun max(a:Int,b:Int)=if (a>b) a else b
//这样是编译不过的
fun max(a,b)=if (a>b) a else b
//kotlin类型推导基本上只能用作声明变量
var a=10;


可以看出,kotlin的类型推导基本上只是一个简单的根据值推断出类型的过程

我们看看haskell的

--这样完全可以
max' a b=if a>b then a else b


所以haskell的类型推导还包括了上下文的类型推导,实际上我们在ghci里查看他的类型,会发现结果是,我们先将Ord看成一个接口,所以haskell可以通过上下文自动推导出需要传入的值需要实现Ord接口(一个可以比较的接口)

这种上下文的类型推导,一般在命令式语言里很难实现,而在函数式语言里相对容易,因为函数式语言每个语句都有值,可以使用动态分析来得到返回值,而且函数式语言没有复杂的控制结构,方便分析。

max' :: (Ord a)=>a->a->a


当然,虽然haskell的类型推导很强大,不过在函数比较复杂的情况下,如果不写明类型,很容易让函数使用者无所适从,因为单看语句很难明白要传入什么,会返回什么。

类型系统

我们往常在静态语言里写代码的时候,都是将类型声明和函数本身混合在一起,例如下面这个函数,即包括了访问控制符public,又包括了函数名max,参数名a,b

public int max(int a,int b)
{
return a>b?a:b;
}


在接触haskell之前,我觉得这样挺自然的,不过接触haskell的类型和函数实现分开写之后,感觉这样反而会使代码更清晰。

--类型声明
max' :: (Ord a)=>a->a->a
--实现
max' a b=if a>b then a else b


我们不断在新语言里加一些新结构,语法糖,很大原因就是希望代码看起来更具结构性,更简洁,例如for来替换while,switch来替换if else,那其实我个人觉得,将类型声明和代码主体分开写,也是一种使代码更简洁的方法。不知道大家怎么看。

haskell因为有不全调用以及高阶函数的存在,所以他的类型声明第一次看的时候都会略显怪异,每个参数都是用->来间隔,不过习惯了高阶函数就好。

addThree :: Int -> Int -> Int -> Int
addThree x y z = x + y + z
--其实就等价于
addThree :: Int ->( Int -> (Int -> Int))
addThree x y z = x + y + z


如果写的不是实际的类型而是类型变量,其实就和其他语言里的泛型差不多

--haskell
ghci> :t head
head :: [a] -> a

--等价的java声明
public<T> T head(T[] array){}


再看下面这个,其实也和java泛型加类型参数的上限差不多

ghci> :t (==)
(==) :: (Eq a) => a -> a -> Bool
--等价的java声明 一直想吐槽设定java类型参数的接口限制用的是extends关键字而不是implement
public<T extends Eq> T head(T[] array){}


虽然我看的几本书上都说haskell的类型声明typeclass比其他语言的泛型强很多。。其实我还是觉得差不多滴,目前看来,haskell比其他语言强很多的特性基本上就是,列表推导,高阶函数 ,其他的特性基本上都是这两个引申出来的。

欢迎关注我的github

https://github.com/luckyCatMiao
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  haskell class 语言 文档