Skip to content
Snippets Groups Projects
Commit d8643d22 authored by joel.vonderwe's avatar joel.vonderwe
Browse files

HK functions

parent 29933c50
No related branches found
No related tags found
No related merge requests found
package ch.hepia.tpscala
/* Implémentez les fonctions suivantes. Vous ne pouvez utiliser que les
* méthode de 'List' vues dans les exercices précédents.
*/
object HKFunc {
/* La fonction 'map' applique une fonction 'f' sur chaque élément de
* la liste 'as'. La liste résultat doit avoir la même longueur que
* l'argument.
*/
def map[A,B]( as: List[A] )( f: A=>B ): List[B] = {
def mapRec(as: List[A], news : List[B]) : List[B] = {
as match {
case Nil => news.reverse
case a :: rest => mapRec(rest, f(a) :: news)
}
}
mapRec(as, Nil)
}
/* La fonction 'filter' utilise le prédicat 'f' pour déterminer quel
* élément garder. Le résultat peut être vide, mais l'ordre doit
* être préservé.
*/
def filter[A]( as: List[A] )( f: A=>Boolean ): List[A] = {
def filterRec(as: List[A], news : List[A]): List[A] = {
as match {
case Nil => news.reverse
case a :: rest if f(a) => filterRec(rest, a :: news)
case _ :: rest => filterRec(rest, news)
}
}
filterRec(as, Nil)
}
/* Réduit une liste 'as' en utilisant une opération binaire 'f'. On
* supposera que 'as' n'est pas vide.
*/
def reduce[A]( as: List[A] )( f: (A,A)=>A ): A = {
def reduceRec(as: List[A], acc : A): A = {
as match {
case Nil => acc
case a :: rest => reduceRec(rest, f(acc, a))
}
}
reduceRec(as.tail, as.head)
}
/* Transforme une fonction 'f' en une fonction s'appliquant sur une
* liste. Utiliser la fonction 'map' définie ci-dessus
*/
def lift[A,B]( f: A=>B ): List[A]=>List[B] = {
(as: List[A]) => {
map(as)(f)
}
}
/* DIFFICILE. Transforme une liste 'as' au moyen de la fonction 'f'.
* Cette fonction est appliquée à chaque élément de 'as' pour
* produire une nouvelle liste (qui peut être vide). Le résultat est
* la concaténation de chaque nouvelle liste en respectant l'ordre.
*/
def bind[A,B]( as: List[A] )( f: A=>List[B] ): List[B] = {
def bindRec(as: List[A], bs: List[B]): List[B] = {
as match {
case Nil => bs
case a :: rest => bindRec(rest, bs ++ f(a))
}
}
bindRec(as, Nil)
}
}
package ch.hepia.tpscala
import org.scalatest.funsuite.AnyFunSuite
import HKFunc._
class HKFunc5Suite extends AnyFunSuite {
val i0 = List[Int]()
val is = List( 1, 2, 3, 4 )
test("map") {
assert( map( i0 )(_ + 1 ) == i0 )
assert( map( is )(_ + 1 ) == List( 2, 3, 4, 5 ) )
assert( map( is )(_ * 2 ) == List( 2, 4, 6, 8 ) )
}
test("filter") {
assert( filter( i0 )(_ % 2 == 0 ) == i0 )
assert( filter( is )(_ % 2 == 0 ) == List( 2, 4 ) )
}
test("reduce") {
assert( reduce( is )( _ + _ ) == is.sum )
assert( reduce( is )( _ * _ ) == 24 )
}
test("lift") {
val f = (_:Int) + 1
val g = (_:Int) * 2
val id = lift[Int,Int]( identity )
assert( id(i0) == i0 )
assert( id(is) == is )
val h1 = lift( f andThen g )
val h2 = lift(f) andThen lift(g)
assert( h1(i0) == h2(i0) )
assert( h1(is) == h2(is) )
}
test("bind") {
val k = (i:Int) => if( i%2 == 0 ) List( -i, i ) else Nil
val l = (i:Int) => List( i, i )
assert( bind( i0 )( k ) == i0 )
assert( bind( is )( k ) == List( -2, 2, -4, 4 ) )
assert( bind( is )( l ) == List( 1, 1, 2, 2, 3, 3, 4, 4 ) )
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment