2013-02-10 55 views
2

我想学习标准毫升的新球衣,但我不明白如何迭代列表。如何迭代列表?

我想创建一个函数,它接受一个值和一个函数列表,并返回另一个字符串列表,如果当前函数在给定值时返回true。

功能就像这样('a -> bool) * string,即一对函数和它的名字串。

该函数是一个curried函数,因此它的定义类似于“fun it x xs”。

我想非递归地做到这一点。

任何人都可以帮助我开始吗?

+0

为什么你想这样做,非递归? ML的列表结构自然是递归的。 – voithos 2013-02-10 23:21:40

+0

我很确定在SML中没有“非递归”的东西。没有循环控制流程结构。如下所述,你可以使用foldr,但这只是一个使用递归的高阶函数。 – dbmikus 2013-06-14 14:25:25

+1

你可以在标准ML中编写命令式的代码,但并不漂亮。既有'while'又有'ref',例如'val x = ref 0; val_ = while!x <10 do x:=!x + 1'。 – 2013-08-06 11:27:28

回答

0

一个自然而直接的函数可以很容易地用递归写出来。

fun itr x fs = 
    case fs 
    of [] => [] 
    | (f, s) :: fs' => if f x 
         then s :: itr x fs' 
         else itr x fs' 

或者,如果你不想在你的函数明确递归,您可以使用foldr

fun itr x fs = 
    List.foldr (fn ((f, s), ss) => 
    if f x 
    then s :: ss 
    else ss) [] fs 

而且,itr是不是一个非常翔实的名字,所以你可能想选择一个不同的,更好地描述了什么是你正在尝试做的。

0

所以,如果我理解正确的话,你希望能够调用你的函数是这样的:

itr 
    3 
    [ ((fn i => i > 3), "greaterThanThree"), 
     ((fn i => i mod 2 = 1), "odd"), 
     ((fn i => 12 mod i = 0), "dividesTwelve") 
    ] 

和得到的结果一样["odd", "dividesTwelve"](因为odddividesTwelve是两个功能使用时就返回true3)。

我有这个权利吗?

因此,我们可以通过书写开始:

(* Given a value and a list of named Boolean functions, returns a list of the names of the 
* functions that return true for value. 
*) 
fun itr value namedFunctions = 
    ... 

既然你说你想“做这个非递归”,我认为你的意思是,你要使用的列表功能标准ML基础库,允许您通过提供独立处理列表元素的函数来处理列表;这些函数当然是使用递归实现的,但是如果itr只是代表它们,那么itr本身不需要递归。

鉴于这些要求,我看到两种方法。


一种方法是通过使用List.filtersee List.filter documentation here)得到的只是关于value调用时返回true的的namedFunctions元素开始。要做到这一点,我们需要一个函数,命名函数(一('a -> bool) * string,其中'avalue类型),并返回true如果命名的函数返回true;那就是:

(* A function that, given a named Boolean function, returns whether it returns true for 
* value. 
*) 
fn (f, _) => f value 

来让我们叫List.filter像这样:

(* A list of the elements of namedFunctions that return true for value. *) 
List.filter (fn (f, _) => f value) namedFunctions 

一旦我们有了这一点,我们需要使用List.mapsee List.map documentation here),以获得每个功能的只是名字:

(* A list of the names in namedFunctions that return true for value. *) 
List.map #2 (List.filter (fn (f, _) => f value) namedFunctions) 

(其中#2是提取元组或记录的组件2的函数;在命名为f联合,#2 namedFunction是名称)。

将其组合在一起:

(* Given a value and a list of named Boolean functions, returns a list of the names of the 
* functions that return true for value. 
*) 
fun itr value namedFunctions = 
    List.map #2 (List.filter (fn (f, _) => f value) namedFunctions) 

另一种方法是既过滤和映射组合到单个步骤中,通过使用List.mapPartial(见List.mapPartial documentation here)。相反,正是我们想要的元素用一个函数,命名函数,并返回一个布尔值,然后将它们转换成我们希望通过使用一个函数,命名函数,并返回其名称形式的第一选择,我们可以结合步骤通过使用带有命名函数的函数,并且仅当我们需要时返回其名称

标准ML,当我们想要的,我们用option来表示的值并不总是存在的;例如,string option手段“是一个字符串,有或全无”(see Option.option documentation here;值得注意的是,虽然它的记录为Option.option,它也可作为刚刚option)。所以,这里的,需要一个命名函数返回只有当它为value返回true其名称的功能:

(* A function that, given a named Boolean function, returns its name if it returns true 
* for value, and nothing if it returns false. 
*) 
fn (f, name) => if f value then SOME name else NONE 

这种功能被称为“部分功能” —它只是的一部分返回一个值其领域—,我们可以使用List.mapPartial检索其结果只有那些地方都返回一个情况:

(* Given a value and a list of named Boolean functions, returns a list of the names of the 
* functions that return true for value. 
*) 
fun itr value namedFunctions = 
    List.mapPartial (fn (f, name) => if f value then SOME name else NONE) namedFunctions 

一般来说,要应用到List.map的结果的任何时间或反之亦然,您可以使用List.mapPartial将两个步骤组合在一起。 (在任何给定的情况下,但是,它可能是也可能不是一个好主意,这样做。我推荐哪一个更清晰。)