Haskell学习重要的方法之一,就是多加练习,习惯函数式编程思维。前面的基础学扎实了,这样就可以在后面的学习中,能够比较容易理解更复杂的概念。Haskell的基础知识还是比较容易理解的,这里收集了一些习题,为大家练习参考。
习题
1.实现以下功能,而不查看库中的代码:
-- 返回 list 的第一个元素. head :: [a] -> a -- 将list的第一个元素丢弃,返回剩余部分. tail :: [a] -> [a] -- 将一个函数应用到所有元素,并且将结果以list返回. map :: (a -> b) -> [a] -> [b]
请记住,当您想要发出错误时(例如head作用于空列表中),您可以使用以下函数:
error :: String -> a
此函数已由标准库提供 - 您不需要(也不能!)用库中的,请自己编写它。
另外,请确保通过引入如下代码行,来隐藏这些函数的标准库版本
import Prelude hiding (map, head, tail)
否则,在测试代码时会出现错误,因为编译器不会知道您所使用的函数版本。
2. 在Haskell中,除了定义自己的函数外,还可以定义自己的二元运算符。库作者经常使用此功能,并且您经常会在Haskell代码中看到一些奇怪的运算符。类似于以下示例:
-- 奇怪的操作符例子! -- 11 <<!>> 10 == 21 (<<!>>) :: Int -> Int -> Int x <<!>> y = if x > y then x + y else x - y
为了与Haskell的精神保持一致,让我们从定义两个自己的运算符:
-- 定义你自己的 list 索引操作符,获取list中指定位置的原始值. (!!) :: [a] -> Int -> a -- 定义list 连接操作符. (++) :: [a] -> [a] -> [a]
和以前一样,记得Prelude通过import语句隐藏这些运算符的版本:
import Prelude hiding ((!!), (++))
3.实现以下功能,而不查看其他实现代码。不要忘记隐藏Prelude版本,就像之前的练习一样。
-- 获取list的前面几个元素 take :: Int -> [a] -> [a] -- 获得重复无数次元素的列表 repeat :: a -> [a] -- 获得list长度,元素个数. length :: [a] -> Int -- "Fold" 遍历 list. 该函数接收三个参数输入: -- 1. 一个用来聚合结果的函数. -- 2. 一个初始值 -- 3. 用来聚合结果的list. -- 比如求一个list中所有元素的和 : -- add x y = x + y -- foldl add 0 myList -- 求所有myList中元素的累加和 -- 求一个list中所有元素的累积乘积: -- mul x y = x * y -- foldl mul 1 myList -- myList所有元素的累积乘积 foldl :: (a -> b -> a) -> a -> [b] -> a
4.实现以下功能:
-- 检查某个整数是否在整数列表中 elem :: [Int] -> Int -> Bool -- 实现从右边来进行的fold函数. -- 类似于foldl,只是这次从list的右边向左来进行运算. foldr :: (a -> b -> b) -> b -> [a] -> b -- 丢弃前面n个字符,获得新的列表. drop :: [a] -> Int -> [a] -- 将列表重复复制指定次数,并且返回结果 replicate :: Int -> [a] -> [a] -- 将两个lists组合成一个二元组列表. zip :: [a] -> [b] -> [(a, b)]