IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Caml Discussion :

[OCaml] Error: This expression has type..


Sujet :

Caml

  1. #1
    Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2009
    Messages
    53
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2009
    Messages : 53
    Points : 60
    Points
    60
    Par défaut [OCaml] Error: This expression has type..
    Je veux écrire un programme pour inverser les valeurs d'une liste;
    t=[| 1, 2, 3 |]
    inverse t donne:
    t=[| 3, 2, 1 |]

    Ca donne l'erreur suivante

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    111	 let inverse t = let lg=A.length t in
    112			 let rec inverse_rec i =function
    113                                 0 -> t
    114				|i -> let tmp = t.(i-1) in
    115						t.(i-1) <- t.(lg-i);
    116						t.(lg-i) <- tmp;
    117						inverse_rec (i-1)
    118			 in inverse_rec (lg/2);;
     
     
     
     
    line 117, characters 6-23:
    Error: This expression has type int -> 'a array
           but an expression was expected of type 'a array
    Je ne comprend pas
    A votre aide, merci

  2. #2
    Membre éprouvé
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    309
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 309
    Points : 928
    Points
    928
    Par défaut
    Citation Envoyé par jamboo Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    111	 let inverse t = let lg=A.length t in
    112			 let rec inverse_rec i =function
    113                                 0 -> t
    114				|i -> let tmp = t.(i-1) in
    115						t.(i-1) <- t.(lg-i);
    116						t.(lg-i) <- tmp;
    117						inverse_rec (i-1)
    118			 in inverse_rec (lg/2);;
     
    line 117, characters 6-23:
    Error: This expression has type int -> 'a array
           but an expression was expected of type 'a array
    Comme tu dois le savoir, (o)caml est un langage à "inférence de type", c'est à dire qu'il tente de deviner le type de tes fonctions. Il suit pour ça un certain nombre de règles. L'une d'entre elle est que quand tu as un match, toutes les branches *doivent* avoir le même type.

    Pour ton match, dans la première branche, il trouve "t", qui est un tableau. Il en déduit que le match doit retourner un "'a array" (prononcer "tick a array" ou "alpha array"), ce qui signifie un "tableau de n'importe quoi".
    Dans la deuxième branche, il trouve "autre chose" (on va voir quoi). Il te répond
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Error: This expression has type int -> 'a array
           but an expression was expected of type 'a array
    commençons par la fin : but an expression was expected of type 'a array ==> on retrouve notre 'a array. Il te dit que c'est ça qu'il attend.
    Error: This expression has type int -> 'a array ==> il trouve que tu es en train de rendre une fonction, de type int -> 'a array. Or tu tentes de retourner inverse_rec (i-1), soit la fonction inverse_rec déjà appliqué à un entier. Donc il te dit que inverse_rec (i-1) est de type int -> 'a array, ce qui signifie que inverse_rec est de type int -> int -> 'a array. Donc une fonction à deux arguments !

    Mmmh, regardons la définition de inverse_rec:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    112			 let rec inverse_rec i =function
    donc, on a une argument i puis... oh, function ! qui veut dire qu'on attend un deuxième argument ! le voilà le problème ! Le pattern matching après n'est pas sur i, mais sur un deuxième argument

    Donc là plusieurs possibilité. Soit tu retires le i, soit tu remplaces function par match i with (et sans doute la seconde branche par | _ ->), soit tu remplaces function par if i = 0 then ... else .... Pour cette dernière option, puisque tu as des ; dans la branche else, il te faudra parenthéser, par exemple en faisant else begin ... end.

    Je pense qu'on pourrait argumenter pour les trois options qui ont leur pour et leur contre. Personnellement j'aurais penché vers le if, malgré le begin ... end parce que le test est une simple égalité sans destruction, et qu'il n'y a pas de variable à lier. Mais c'est une question de gout.

    Si tu as besoin de clarification (ce dont je ne doute pas...), n'hésite pas à demander.

    Vali valou

  3. #3
    Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2009
    Messages
    53
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2009
    Messages : 53
    Points : 60
    Points
    60
    Par défaut
    Merci pour ta réponse, ça explique pas mal de chose.

    PS: Je suis désolé, je pense que sans faire expirer j'ai appuyer sur le bouton "pas cool" et je ne sais pas comment enlevé je ss en peu nouveau mais sache c'est 100x

    Alors Je l'ai modifié comme la suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    Avec match;
     
    let inverse1 t = let lg=A.length t in
    			 let rec inverse_rec i =
    			 	match i with
    				 0 -> t
    				|_ -> let tmp = t.(i-1) in
    						t.(i-1) <- t.(lg-i);
    						t.(lg-i) <- tmp;	
    						inverse_rec (i-1)
    			in inverse_rec (lg/2);;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    avec if..then..else
     
    let inverse2 t = let lg=A.length t in
    			 let rec inverse_rec i =
    			 	if i=0 then
    			 		t
    			 	else
    				 	let tmp = t.(i-1) in
    						t.(i-1) <- t.(lg-i);
    						t.(lg-i) <- tmp;
    						inverse_rec (i-1)
    			in inverse_rec (lg/2);;
    Les deux codes marche nikel. Tu as bien dit qu'il faillait utiliser begin..end alors que le programme marche sans. Quand est-ce qu'on utilise begin..end donc?

  4. #4
    Membre éclairé
    Avatar de GnuVince
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2004
    Messages
    679
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2004
    Messages : 679
    Points : 803
    Points
    803
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    let reverse arr =
      let rec loop i j =
        if i >= j then
          arr
        else
          let t = arr.(i) in
            arr.(i) <- arr.(j);
            arr.(j) <- t;
            loop (i+1) (j-1)
      in
        loop 0 (Array.length arr - 1)

  5. #5
    Membre éprouvé
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    832
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 832
    Points : 1 104
    Points
    1 104
    Par défaut
    L'idée de "oh tiens `i` et `j` se rencontrent au milieu" est amusante, mais dans l'absolu une boucle `for` me semble tout de même plus lisible.

    Une version plus sûre, car ne détruisant pas le tableau en entrée (et si c'était l'effet attendu, pourquoi ne pas renvoyer unit ?)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    let reverse t =
      let len = Array.length t in
      Array.init len (fun i -> t.(len - 1 - i))

  6. #6
    Membre régulier
    Étudiant
    Inscrit en
    Juillet 2010
    Messages
    102
    Détails du profil
    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2010
    Messages : 102
    Points : 110
    Points
    110
    Par défaut
    Citation Envoyé par jamboo Voir le message
    Quand est-ce qu'on utilise begin..end donc?
    Pour délimiter clairement une séquence d'instruction. C'est surtout utile quand on utilise des if ... then ... else ...

    En effet, la structure est :

    if condition then instruction 1 else instruction 2

    Les instructions doivent être clairement délimités. Or comme il n'y a pas de endif, comment pourrait on savoir si une instruction située après un else (par exemple) est soumise à la condition ou doit être exécutée quelque soit le cas ? Par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    # let f x = 
      if x = 2 then print_string "ok"
      else print_string "non";
      print_string "\nprogramme fini"
    ;;
    Comment savoir si le l'instruction print_string "programme fini" fait partie du else ou doit être exécutée quoi qu'il arrive ? Si on regarde, on a :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    val f : int -> unit = <fun>
    # f 2;;
    ok
    programme fini- : unit = ()
    # f 3;;
    non
    programme fini- : unit = ()
    La convention, c'est qu'après un then / un else, on prend une instruction. Mais alors comment faire si je veux que "programme fini" ne soit affiché que lorsque x est différent de 2 ? Et bien je "remplace mes deux instructions par une séquence d'instructions, comme ça, ça marche.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    # let f x = 
      if x = 2 then print_string "ok"
      else begin print_string "non";
      print_string "\nprogramme fini" end
    ;;        
    val f : int -> unit = <fun>
    # f 2;;
    ok- : unit = ()
    # f 3;;
    non
    programme fini- : unit = ()
    Du coup, tu devrais comprendre ce qui se passe dans le code suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     # let f x =
        if x = 2 then print_string "machin";
                 print_string "truc"
        else ()
      ;;      
    Error: Syntax error
    # let f x =
      if x = 2 then begin print_string "machin";
               print_string "truc" end
      else ()
    ;;        
    val f : int -> unit = <fun>
    # f 2;;
    machintruc- : unit = ()
    #

  7. #7
    Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2009
    Messages
    53
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2009
    Messages : 53
    Points : 60
    Points
    60
    Par défaut
    Merci pour les explications

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 6
    Dernier message: 19/03/2013, 13h47
  2. Réponses: 4
    Dernier message: 26/06/2012, 09h13
  3. Réponses: 0
    Dernier message: 12/03/2010, 13h24
  4. Réponses: 3
    Dernier message: 06/07/2008, 20h51

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo