List 映射到列表,最后一个列表元素除外
如何最好地映射列表的所有元素(最后一个列表元素除外) 假设我们有一个列表List 映射到列表,最后一个列表元素除外,list,haskell,functional-programming,map-function,List,Haskell,Functional Programming,Map Function,如何最好地映射列表的所有元素(最后一个列表元素除外) 假设我们有一个列表让l=[1,2,3,4],并且想要得到[2,3,4,4] 我确实有一个解决方案,但它不像“功能性”的方式(在ghci中): 设l=[1,2,3,4] 让len=toIntegral$length l——以避免类型不匹配的整数Int 设l1=zip l[1..] 设l2=map(\(x,y)->如果ya,而不是a->b 或者,你也可以这样做 mapBut1 f (x:y:xs) = f x : mapBut1 f (y:xs)
让l=[1,2,3,4]
,并且想要得到[2,3,4,4]
我确实有一个解决方案,但它不像“功能性”的方式(在ghci中):
设l=[1,2,3,4]
让len=toIntegral$length l——以避免类型不匹配的整数Int
设l1=zip l[1..]
设l2=map(\(x,y)->如果y
不是很好…我真的希望有更好的方法!由于我是函数式编程的新手,我不知道从哪里开始寻找它。只需重新编写
map
,但在只有一个元素时,请做一个特例:
mapBut1 :: (a -> a) -> [a] -> [a]
mapBut1 f [] = []
mapBut1 f [x] = [x]
mapBut1 f (x:xs) = f x : mapBut1 f xs
现在,即使是无限列表,它也能工作,比计算长度快得多,并且更具可读性。请注意,这会将函数类型限制为a->a
,而不是a->b
或者,你也可以这样做
mapBut1 f (x:y:xs) = f x : mapBut1 f (y:xs)
mapBut1 f other = other
它们是等价的定义,但后者使用的模式匹配少了1个。不过,我更喜欢前者,因为它更能显示正在处理的案例。如果您不关心性能,也可以使用标准库(无特殊导入)
你可以写
哪里
:要映射的函数f
:要映射的列表列表
import Data.List (tails)
mapButLast :: (a -> a) -> [a] -> [a]
mapButLast f = foldr g [] . tails where
g (x:_:_) r = f x : r
g xs _ = xs
或者用适当的方式,我们就写
mapButLast f = para g [] where
g x [] r = [x]
g x _ r = f x : r
在哪里
是什么让这最后一个元素如此特别 我知道它没有回答你的问题,但我会考虑一种类似的类型。
data Foo a = Foo a [a]
和一个合适的函子。我只想添加一个替代方法,使用列表理解并尝试比较解决方案(第一次尝试时,请告诉我是否做得不对) 执行
ghc -O2 --make allbutlast.hs
./allbutlast --output allbutlast.html
示例报告:非常好!只有一件小事:代码最后一行中的
xs
不应该是x
,因为我们正在匹配长度为1的列表吗?@mort首先,Haskell不关心变量的名称,因此将xs
重命名为x
不会改变代码的含义。其次,该行匹配的是与模式(x:xs)
不匹配的任何内容,可以是[\u]
或[]
([\u]
表示一个元素的列表)。所以它的意思是除了模式(x:xs)
之外的任何东西都会被匹配,而不是单个元素会被匹配。然而,您确实让我发现了代码中的一个小错误。这是一个很好的模式@我在中编辑了更多内容,带有链接para
是“明显”的方式,但我喜欢使用tails
来获得一个假装的para。尽管如此,与它们并排在一起,我不太确定它实际上比para
本身更容易理解。@J.Abrahamson最终它们是一样的-使用tails
是para
所做的(最多跳过一个节拍)。使用tails
它甚至可以重用结构。有时非标准的parafz[]=z;parafzxs@(x:t)=fxxs(parafzt)
可能更可取,这正是下面的内容。。。tails
variant.oh和。这并不是那么糟糕的性能,因为init
是惰性的,并且last list
expr。在评估之前,在WHNF中。我敢打赌,它的答案与O(n)遍历到最后一个ELM,这可能是很好的优化GHC。DavidUnric,这有相当差的性能特点。特别是,它不是一个好的拖缆:它会将整个输入列表保存在内存中,直到最后一个元素被计算。我喜欢这个解决方案,因为它甚至对初学者都可读;)
para f z (x:xs) = f x xs (para f z xs)
para f z [] = z
data Foo a = Foo a [a]
reverse $ last l : [f x | x <- tail (reverse l)]
cabal update
cabal install QuickCheck
cabal install -j --disable-tests criterion
ghc -O2 --make allbutlast.hs
./allbutlast --output allbutlast.html