2015-11-30 2 views
0

Je suis novice en F # et j'ai joué avec les dossiers et les ai changés. J'essaie d'appliquer ma propre fonction sans utiliser de carte à ma liste. C'est ce que j'ai jusqu'ici. Je me demande simplement si ma façon d'écrire une cartographie sans utiliser la carte fonctionne correctement.Dossiers F # et mappage

module RecordTypes = 
// creation of simple record 
// immutable by default - key word mutable allows that to change 
type Student = 
    { 
     Name : string 
     mutable age : int 
     mutable major : string 
    } 
// setting up a few records with student information 
// studentFive.age <- studentFive.age + 2 ; example of how to change mutable variable 
let studentOne = { Name = "bob" ; age = 20 ; major = "spanish" } 
let studentTwo= { Name = "sally" ; age = 18 ; major = "english" } 
let studentThree = { Name = "frank" ; age = 22 ; major = "history" } 
let studentFour = { Name = "lisa" ; age = 19 ; major = "math" } 
let studentFive = { Name = "john" ; age = 17 ; major = "philosophy" } 


// placing the records into a lits 
let studentList = [studentOne; studentTwo; studentThree ;studentFour; studentFive] 



// placing the records into a lits 
let studentList = [studentOne; studentTwo; studentThree ;studentFour; studentFive] 

// itterate through a list and printing each records 
printf "the unsorted list of students: \n" 
studentList |> List.iter (fun s-> printf "Name: %s, Age: %d, Major: %s\n" s.Name s.age s.major) 

// a sort of the records based on the name, can be sorted by other aspects in the records 
let sortStudents alist = 
    alist 
    |> List.sortBy (function student -> student.age) 

let rec selectionSort = function 
    | [] -> [] //if the list is empty it will return an empty list 
    | l -> let min = List.min l in // otherwise set a min variable and use the min function to find the smallest item in a list 
      let rest = List.filter (fun i -> i <> min) l in // set a variable to hold the rest of the list using filter 
                  // Returns a new collection containing only the elements of the collection for which the given predicate returns true 
                  // fun sets up a lambda expression that if (i -> i <> (not equal boolean) min) if i(the record is not the min put it into a list)   
      let sortedList = selectionSort rest in   // sort the rest of the list that isnt the min 
      min :: sortedList // :: is an operator that creates a list, left elem appended to right side 

let unsortedList = studentList 
let sortedList = selectionSort unsortedList 
printfn "sorted list based on first name:\n" 
sortedList |> List.iter(fun s -> printf "Name: %s, Age: %d, Major: %s\n" s.Name s.age s.major) 

ici est où j'ai essayé de créer ma propre carte avec fonction foo

let foo x = x + 1 
let applyOnEachElement (list : Student list) (someFunction) = 
    list |> List.iter(fun s -> someFunction s.age) 

//let agedStudents = applyOnEachElement studentList foo 
printf " the students before function is applied to each: \n" 
sortedList |> List.iter(fun s -> printf "Name: %s, Age: %d, Major: %s\n" s.Name s.age s.major) 

printf " the student after function is applied to each: \n" 
agedStudents |> List.iter(fun s -> printf "Name: %s, Age: %d, Major: %s\n" s.Name s.age s.major) 
+0

Où, dans le code ci-dessus , est-ce que vous essayez d'écrire 'map' sans carte? –

+1

Il serait utile si vous fournissez du code qui * compile * et démontre le problème aussi succinctement que possible. Voir [Comment demander] (http://stackoverflow.com/help/mcve) pour un conseil sur ce sujet. –

+0

BTW, 'map' peut être implémenté dans deux lignes de code - quatre si vous avez besoin d'être récursif de queue. –

Répondre

3

Dans le dernier commentaire, l'OP mentionne sa solution presque complète. Avec un peu de formatage ajouté et oublié match construction, il se présente comme suit:

let rec applyOnEachElement2 (list: Student list) (f) = 
    match list with 
    | [] -> [] 
    | hd :: tl -> hd::applyOnEachElement2 f tl 

Ceci est assez proche de la mise en œuvre correcte de map fonction! Il y a seulement deux questions:

  • lorsque vous appelez applyOnEachElement2 récursive, vous avez changé les paramètres
  • le paramètre f est passé récursive mais jamais réellement utilisé pour quoi que ce soit

Pour corriger cela, tout ce que vous avez besoin est pour changer l'ordre des paramètres (je le ferai sur les arguments de la fonction pour obtenir les paramètres dans le même ordre que la norme map) et appelez la fonction f sur hd sur la dernière ligne (de sorte que la fonction retourne une liste d'eleme transformé NTS):

let rec applyOnEachElement2 f (list: Student list) = 
    match list with 
    | [] -> [] 
    | hd :: tl -> (f hd)::applyOnEachElement2 f tl 

Vous pouvez également faire générique en laissant tomber l'annotation de type, ce qui vous donne une fonction avec la même signature de type que le construit en List.map:

let rec applyOnEachElement2 f list = 
    match list with 
    | [] -> [] 
    | hd :: tl -> (f hd)::applyOnEachElement2 f tl