我试图以递归方式定义ghci中的地图。到目前为止,我想出的是:
let mymap f (x:xs) = if null xs then [] else f x : map f xs
我现在要做的是简化它并对代码中的列表进行硬编码,即编写一个map函数,该函数将函数作为参数并执行真实映射所做的但仅限于具体列表,例如[1,2,3,4,5]。 这样的事情可能吗?
答案 0 :(得分:6)
首先,你的地图功能并不完全正确。如果我要输入mymap (+1) [1]
,我希望得到[2]
,但我会得到[]
。如果我尝试mymap (+1) []
,我的程序会因模式匹配失败而崩溃,因为您尚未定义该情况。相反,请考虑将mymap
定义为
mymap :: (a -> b) -> [a] -> [b]
mymap f [] = []
mymap f (x:xs) = f x : mymap f xs
如果你想用if语句内联,那么你必须做
mymap f xs = if null xs then [] else f (head xs) : mymap f (tail xs)
这些基本上是相同的,但在我看来,第一个更容易阅读。
如果您想使用mymap
来定义仅映射到特定列表的函数,您可以非常轻松地执行此操作
mapOnMyList :: (Int -> b) -> [b]
mapOnMyList f = mymap f [1, 2, 3, 4, 5]
或以无点形式
mapOnMyList = (`mymap` [1, 2, 3, 4, 5])
使用mymap
作为中缀运算符。这相当于flip mymap [1, 2, 3, 4, 5]
,但通常首选运算符表单,因为flip
不一定可以自由执行。
您也可以使用列表推导来执行此操作:
mymap f xs = [f x | x <- xs]
或者,如果您想对列表进行硬编码
mapOnMyList f = [f x | x <- [1, 2, 3, 4, 5]]