如何让函数 [a] ->[a] 对 [(a,Int)] 进行操作? [英] How to let a function [a] -> [a] operate on [(a,Int)]?

查看:26
本文介绍了如何让函数 [a] ->[a] 对 [(a,Int)] 进行操作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现自己经常按照以下模式编写代码:

I find myself often writing code following the pattern:

foo xs = map snd $ filter ((< 10).fst) $ zip xs [0..]

bar ys = map snd $ sortBy (compare `on` fst) $ zip ys [0..]

现在我想把它抽象出来

foo = indexesOf (filter (<10))

bar = indexesOf sort

indexesOf :: ([a] -> [a]) -> [a] -> [Int] 
indexesOf f xs = map snd $ magick $ zip xs [0..] where
    magick = undefined

如何执行magick?

推荐答案

您的类型签名不起作用.您需要能够为传递的函数提供一个元组列表,这意味着您必须使用更高等级的类型来强制它成为多态的,或者在您的类型签名中明确提及元组.

Your type signature won't work. You need to be able to give the passed function a list of tuples, which means that you either have to use higher-rank types to force it to be polymorphic, or explicitly mention tuples in your type signature.

没有这个,你就不能看内部"函数来查看它如何重新排列列表的元素.事实上,给定你的类型签名,传递的函数可以对列表做任何它想做的事情,包括插入甚至不在列表中的元素!

Without this, you can't "look inside" the function to see how it rearranges the elements of the list. In fact, given your type signature the passed function could do anything it wanted to the list, including inserting elements that weren't even in there to begin with!

以下是我使用更高等级类型的工作:

Here's what I got to work using higher-rank types:

{-# LANGUAGE RankNTypes #-}

import Data.List (sortBy)
import Data.Ord (comparing)

indexesOf :: (forall b. (b -> a) -> [b] -> [b]) -> [a] -> [Int]
indexesOf f xs = map snd $ f fst $ zip xs [0..]

foo :: (Ord a, Num a) => [a] -> [Int]
foo = indexesOf (filter . ((< 10) .))

bar :: Ord a => [a] -> [Int]
bar = indexesOf (sortBy . comparing)

请注意,我还必须向传递的函数添加一个额外的参数,以告诉它如何从它正在处理的列表的元素中提取它关心的部分.如果没有这个,您将只能使用不检查列表元素的函数,例如 reverse,这不会很有用.

Note that I also had to add an extra argument to the passed function to tell it how to extract the part it cares about from the elements of the list it's working on. Without this, you would only be able to use functions that don't inspect the elements of the list, such as reverse, and that wouldn't be very useful.

在 GHCi 中运行的示例:

> let xs = [42, 0, 7, 3, 12, 17, 99, 36, 8]
> foo xs
[1,2,3,8]
> bar xs
[1,3,2,8,4,5,7,0,6]
> indexesOf (const reverse) xs
[8,7,6,5,4,3,2,1,0]

这篇关于如何让函数 [a] ->[a] 对 [(a,Int)] 进行操作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆