今天这篇文章分析一下ghci交互解释器对类型的推导。

假设有函数fn定义如下:

let fn = map map

现在fn的类型是:

map map :: [a -> b] -> [[a] -> [b]]

推导过程:

1)首先map函数自身的类型为:

map :: (a -> b) -> [a] -> [b]

为了区分开第一个map和第二个map,将另外一个map的类型表示为:

map :: (a' -> b') -> [a'] -> [b']

在调用的过程中,有如下等式关系

(a -> b) -> [a] -> [b] = (a' -> b')

由于curry的原因,此等式等同于

(a -> b) -> ([a] -> [b]) = (a' -> b')

那么,可以得到:

a' = a -> b
b' = [a] -> [b]

将a',b'的值代入[a'] - > [b']最终得到

 [a -> b] -> [[a] -> [b]]

总结,ghci对复杂函数或表达式的类型推导就是一个简单的替换过程,不过有时候一眼看过去会很疑惑,不知道该类型所代表的意义,这是难以避免的。这是因为在haskell中大范围的使用了typeclass的概念,这个概念对应着C++中的模版,想象一下C++模版给代码带来的视觉冲击,初次使用时会很难阅读。在haskell中函数类型声明变得变本加厉,因为typeclass的存在,haskell的类型声明中大部分时候都是简单的小写字母表示,而这些字母本身并不能够带来任何类型信息的提示,大家看看这个被haskell程序员称为"boobs operator"的类型:

(.)(.) :: (a -> b -> c) -> a -> (a1 -> b) -> a1 -> c

一眼看过去大概明白这个函数是干什么的了吗?似乎很难,或许也没有必要去搞明白,不过大家可以尝试去推导一下哦:D

ghci对haskell的类型推导的更多相关文章

  1. Java 8 新特性之泛型的类型推导

    1. 泛型究竟是什么? 在讨论类型推导(type inference)之前,必须回顾一下什么是泛型(Generic).泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据 ...

  2. C++11 - 类型推导auto关键字

    在C++11中,auto关键字被作为类型自动类型推导关键字 (1)基本用法 C++98:类型 变量名 = 初值;   int i = 10; C++11:auto 变量名 = 初值;  auto i ...

  3. 图说函数模板右值引用参数(T&&)类型推导规则(C++11)

    见下图: 规律总结: 只要我们传递一个基本类型是A④的左值,那么,传递后,T的类型就是A&,形参在函数体中的类型就是A&. 只要我们传递一个基本类型是A的右值,那么,传递后,T的类型就 ...

  4. C++11 图说VS2013下的引用叠加规则和模板参数类型推导规则

    背景:    最近在学习C++STL,出于偶然,在C++Reference上看到了vector下的emplace_back函数,不想由此引发了一系列的“探索”,于是就有了现在这篇博文. 前言:     ...

  5. c++相关的类型推导

    c++11和boost库增加许多关于类型推导(编译期)的关键字和类型, 用好这些机制, 对于编写项目的一些组件帮助颇大.正所谓工欲善其事,必先利其器. 1.初始化某种类型的变量 auto var = ...

  6. Effective Modern C++翻译(3)-条款2:明白auto类型推导

    条款2 明白auto类型推导 如果你已经读完了条款1中有关模板类型推导的内容,那么你几乎已经知道了所有关于auto类型推导的事情,因为除了一个古怪的例外,auto的类型推导规则和模板的类型推导规则是一 ...

  7. Swift学习(三)类型推导&基本运算&分支&循环

    一.Swift中类型推导&基本运算 Swift中类型推导 如果一个标识符在定义时有直接赋值,那么可以根据后面赋值的类型,来推导出前面标识符的类型,这样前面标识符的(:类型)可以省略 查看标识符 ...

  8. C++11类型推导

    [C++11类型推导] auto 关键字.这会依据该初始化子(initializer)的具体类型产生参数: 除此之外,decltype 能够被用来在编译期决定一个表示式的类型. 参考:http://z ...

  9. 类型推导:函数模板与auto

    1.从函数模板谈起 函数模板的类型推导机制是在c++98时代就有的,auto的类型推导机制与其基本一致,所以先理解函数模板类型推导. 函数模板可以用如下代码框架表示: #template<typ ...

随机推荐

  1. [BZOJ3527][ZJOI2014]力:FFT

    分析 整理得下式: \[E_i=\sum_{j<i}{\frac{q_i}{(i-j)^2}}-\sum_{j>i}{\frac{q_i}{(i-j)^2}}\] 假设\(n=5\),考虑 ...

  2. Mybatis, 实现一对多

    我这里是拿商品做为例子 不多说直接上代码 Mapper.xml <?xml version="1.0" encoding="UTF-8"?> < ...

  3. 字节对齐#pragma pack

    这是给编译器用的参数设置,有关结构体字节对齐方式设置, #pragma pack是指定数据在内存中的对齐方式. #pragma pack (n)             作用:C编译器将按照n个字节对 ...

  4. react-native 组件之间传值

    1.通过 AsyncStorage 将值保存在本地(最低端的方法) import { AsyncStorage, } from 'react-native'; // 保存 IP AsyncStorag ...

  5. python值的引用传递和go语言的值传递

    一:值传递 实参a 原本指向地址 1638212,代表1638212这个地址的值是3.在swap函数中,实参a将值拷贝给形参a,形参a此时也在内存中拥有地址,地址= xxxx,值为3,在所有的函数体内 ...

  6. SpringBoot系列:二、SpringBoot的配置文件

    SpringBoot的配置文件在resources文件夹下 springboot的配置文件支持两种形式的写法,一种是经典的properties另一种是yml yml通过空格缩进的形式来表示对象的层级关 ...

  7. 阶段1 语言基础+高级_1-3-Java语言高级_1-常用API_1_第8节 Math类_19_Math练习:小学数学真题

    题目 画数轴 解题思路 强转成int类型就会舍弃小数位数 输出最终的数量 如果用Math.ceil的方式的话

  8. C++笔记(2)——一些语法基础知识以及基本算法知识

    今天和PAT无直接相关的关系,主要是关于一些语法/算法的笔记,因为我发现自己的基础还没有打扎实,有些时候看别人的代码还会觉得一头雾水,不明白代码的含义. 一些C/C++语法 先从语法开始吧.这部分很琐 ...

  9. powerdisigner

  10. Postman—上个接口返回数据作为下个接口入参

    //将数据解析成json格式 var data=JSON.parse(responseBody); //获取totalRentPrice值 var totalRentPrice=jsonData.da ...