WKQ*_*WKQ 4 haskell tuples map-function
我必须编写一个执行以下操作的Haskell程序:
Main> dotProduct [(1,3),(2,5),(3,3)] 2
[(2,3),(4,5),(6,3)]
Run Code Online (Sandbox Code Playgroud)
无论有没有map功能,我都要这样做.我已经没有了map,但我不知道如何做到这一点map.
我dotProduct没有map功能:
dotProduct :: [(Float, Integer)] -> Float -> [(Float, Integer)]
dotProduct [] _ = []
dotProduct [(x,y)] z = [(x*z,y)]
dotProduct ((x,y):xys) z = (x*z,y):dotProduct (xys) z
Run Code Online (Sandbox Code Playgroud)
所以我真的需要帮助map版本.
C. *_*ann 13
不要map以某种方式尝试适应,而是考虑如何简化和概括当前的功能.从这开始:
dotProduct :: [(Float, Integer)] -> Float -> [(Float, Integer)]
dotProduct [] _ = []
dotProduct [(x,y)] z = [(x*z,y)]
dotProduct ((x,y):xys) z = (x*z,y):dotProduct (xys) z
Run Code Online (Sandbox Code Playgroud)
首先,我们将使用(:)构造函数重写第二种情况:
dotProduct ((x,y):[]) z = (x*z,y):[]
Run Code Online (Sandbox Code Playgroud)
[]使用第一种情况扩展结果:
dotProduct ((x,y):[]) z = (x*z,y):dotProduct [] z
Run Code Online (Sandbox Code Playgroud)
这相较于第三种情况,我们可以看到,他们除了这是专门为当相同xys的[].所以,我们可以完全消除第二种情况:
dotProduct :: [(Float, Integer)] -> Float -> [(Float, Integer)]
dotProduct [] _ = []
dotProduct ((x,y):xys) z = (x*z,y):dotProduct (xys) z
Run Code Online (Sandbox Code Playgroud)
接下来,概括功能.首先,我们重命名它,然后dotProduct调用它:
generalized :: [(Float, Integer)] -> Float -> [(Float, Integer)]
generalized [] _ = []
generalized ((x,y):xys) z = (x*z,y):generalized (xys) z
dotProduct :: [(Float, Integer)] -> Float -> [(Float, Integer)]
dotProduct xs z = generalized xs z
Run Code Online (Sandbox Code Playgroud)
首先,我们通过操作对其进行参数化,专门用于乘法dotProduct:
generalized :: (Float -> Float -> Float) -> [(Float, Integer)] -> Float -> [(Float, Integer)]
generalized _ [] _ = []
generalized f ((x,y):xys) z = (f x z,y):generalized f (xys) z
dotProduct :: [(Float, Integer)] -> Float -> [(Float, Integer)]
dotProduct xs z = generalized (*) xs z
Run Code Online (Sandbox Code Playgroud)
接下来,我们可以观察到两件事:generalized不再依赖于算术,因此它可以在任何类型上工作; 并且唯一使用的时间z是作为第二个参数f,因此我们可以将它们组合成单个函数参数:
generalized :: (a -> b) -> [(a, c)] -> [(b, c)]
generalized _ [] = []
generalized f ((x,y):xys) = (f x, y):generalized f (xys)
dotProduct :: [(Float, Integer)] -> Float -> [(Float, Integer)]
dotProduct xs z = generalized (* z) xs
Run Code Online (Sandbox Code Playgroud)
现在,我们注意到它f仅用于元组的第一个元素.这听起来很有用,所以我们将其作为一个单独的函数提取:
generalized :: (a -> b) -> [(a, c)] -> [(b, c)]
generalized _ [] = []
generalized f (xy:xys) = onFirst f xy:generalized f (xys)
onFirst :: (a -> b) -> (a, c) -> (b, c)
onFirst f (x, y) = (f x, y)
dotProduct :: [(Float, Integer)] -> Float -> [(Float, Integer)]
dotProduct xs z = generalized (* z) xs
Run Code Online (Sandbox Code Playgroud)
现在我们再次观察到,in generalized,f仅用于onFirst,所以我们再次将它们组合成一个函数参数:
generalized :: ((a, c) -> (b, c)) -> [(a, c)] -> [(b, c)]
generalized _ [] = []
generalized f (xy:xys) = f xy:generalized f (xys)
dotProduct :: [(Float, Integer)] -> Float -> [(Float, Integer)]
dotProduct xs z = generalized (onFirst (* z)) xs
Run Code Online (Sandbox Code Playgroud)
再一次,我们观察到generalized不再依赖于包含元组的列表,所以我们让它适用于任何类型:
generalized :: (a -> b) -> [a] -> [b]
generalized _ [] = []
generalized f (x:xs) = f x : generalized f xs
Run Code Online (Sandbox Code Playgroud)
现在,将代码generalized与此进行比较:
map :: (a -> b) -> [a] -> [b]
map _ [] = []
map f (x:xs) = f x : map f xs
Run Code Online (Sandbox Code Playgroud)
事实证明,onFirst还存在一个稍微更通用的版本,因此我们将替换它们和generalized它们的标准库等价物:
import Control.Arrow (first)
dotProduct :: [(Float, Integer)] -> Float -> [(Float, Integer)]
dotProduct xs z = map (first (* z)) xs
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5715 次 |
| 最近记录: |