6
votes

Listes cycliques dans F #

Est-ce juste moi, ou est-ce que f # ne traite pas de listes cycliques?

J'ai regardé la classe fsharplist par réflecteur et remarquée, que ni la "structure égale" ni les méthodes de longueur vérifient les cycles. Je ne peux que deviner que si 2 fonctions primitives ne vérifient pas, que la plupart des fonctions de la liste ne feraient pas cela non plus.

Si les listes cycliques ne sont pas prises en charge, pourquoi?

merci

PS: suis-je même en train de regarder la classe de la bonne liste?

f#

0 commentaires

4 Réponses :


5
votes

Le type de liste F # est essentiellement une liste liée, où chaque nœud a une «suivante». Ceci en théorie vous permettrait de créer des cycles. Cependant, les listes F # sont immuables. Donc, vous ne pourriez jamais «faire» ce cycle par mutation, vous devriez le faire au moment de la construction. (Puisque vous ne pouviez pas mettre à jour le dernier nœud pour boucler à l'avant.)

vous pourrait em> écrire ceci pour le faire, mais le compilateur l'empêche spécifiquement: P>

> type CustomListNode = { Value : int; mutable Next : CustomListNode option };;

type CustomListNode =
  {Value: int;
   mutable Next: CustomListNode option;}

> let head = { Value = 1; Next = None };;

val head : CustomListNode = {Value = 1;
                             Next = null;}

> let head2 = { Value = 2; Next = Some(head) } ;;

val head2 : CustomListNode = {Value = 2;
                              Next = Some {Value = 1;
                                           Next = null;};}

> head.Next <- Some(head2);;
val it : unit = ()
> head;;
val it : CustomListNode = {Value = 1;
                           Next = Some {Value = 2;
                                        Next = Some ...;};}


3 commentaires

Pas la réponse que je cherchais. Je ne peux pas le tester non plus, car mon F # 1.9.9.9 ne parvient pas à courir :(


Je suppose que le fait qu'ils soient strictement immuables empêche la nécessité de vérifier les cycles.


@Leppie: Non, les listes d'OCAML sont strictement immuables, mais vous pouvez toujours les rendre cycliques et cela ne se dérange pas de vérifier les cycles non plus. Donc, xs = ys comparer avec une liste cyclique dans OCAML est juste suspendu. :-)



5
votes

La réponse est la même pour toutes les langues avec support d'optimisation des appels queue et fonctions de première classe (types de fonctions) Support: il est si facile d'émuler des structures cycliques.

let rec x = seq { yield 1; yield! x};;


1 commentaires

Notez que OCAML vous permet de créer de vraies listes cycliques. Ils seront un lot plus rapide que SEQ .



15
votes

Il existe de nombreuses listes / types de collecte différentes dans F #.

  • f # liste code> type. Comme le dit Chris, vous ne pouvez pas initialiser une valeur récursive de ce type, car le type n'est pas paresseux et non mutable (une immuabilité signifie que vous devez la créer à la fois et que ce n'est pas paresseux signifie que vous ne pouvez pas utiliser F # récursif Valeurs utilisant Soit Rec code>). Comme le dit SSP, vous pouvez utiliser la réflexion pour le pirater, mais c'est probablement un cas que nous ne voulons pas discuter. P> li>

  • Un autre type est SEQ code> (qui est en fait iEnumerable code>) ou la lazyliste code> Type de Powerpack. Ce sont des paresseux, vous pouvez donc utiliser let Rec code> pour créer une valeur cyclique. Toutefois, (autant que je sache) aucune des fonctions qui ne travaillent avec eux ne prennent en compte cycyclique - si vous créez une liste cyclique, cela signifie simplement que vous créez une liste infinie em>, donc le résultat de (par exemple) mapper code> sera une liste potentiellement infinie. p> li> ul>

    Voici un exemple de Lazyliste code> Type: p> xxx pré>

    La question correspond à quels types de données pouvez-vous vous définir. Chris montre une liste mutable et si vous écrivez des opérations qui le modifiez, elles affecteront la liste complète (si vous l'interprétez comme une structure de données infinie). P>

    Vous pouvez également définir des données paresseuses (puto-cycliques). Tapez et implémentez les opérations qui gèrent des cycles, de sorte que lorsque vous créez une liste cyclique et projetez-le dans une autre liste, il créera une liste cyclique à la suite (et non une structure de données potentiellement infinie). P>

    La déclaration de type peut ressembler à ceci (j'utilise le type d'objet, de sorte que nous puissions utiliser l'égalité de référence lors de la vérification des cycles): P>

    let map f (cl:CyclicList<_>) =  
      // 'start' is the first element of the list (used for cycle checking)
      // 'l' is the list we're processing
      // 'lazyRes' is a function that returns the first cell of the resulting list
      //  (which is not available on the first call, but can be accessed
      //  later, because the list is constructed lazily)
      let rec mapAux start (l:CyclicList<_>) lazyRes =
        match l.Value with
        | Nil -> new CyclicList<_>(Nil)
        | Cons(v, rest) when rest.Value = start -> lazyRes()
        | Cons(v, rest) -> 
          let value = Cons(f v, lazy mapAux start rest.Value lazyRes)
          new CyclicList<_>(value)
      let rec res = mapAux cl cl (fun () -> res)
      res
    


1 commentaires

Pourrait être utile de mentionner que cela peut être fait dans OCAML. Je peux même citer la seule application pratique de ces capacités dans la mise en œuvre de fermetures récursives ici: FFConsultance .com / ocaml / avantages / interprétation.html



1
votes

Comme cela a été dit auparavant, votre problème ici est que la liste est immuable, et pour une liste pour être cyclique que vous devez le faire coller dans Son dernier élément, de sorte que cela ne fonctionne pas. Vous pouvez utiliser des séquences, bien sûr.

Si vous avez une liste existante et souhaitez créer une séquence infinie sur celle-ci qui cycle dans les éléments de la liste, voici comment vous pouvez le faire: < / p> xxx


3 commentaires

"Vous devriez l'avoir à coller dans son dernier élément, de sorte que cela ne fonctionne pas". Peut-être mériter d'être souligné que let Rec XS = 1 :: xs crée une liste logicielle immuable cyclique juste bien dans OCAML.


@Jon: C'est intéressant et rend mon esprit enchanté un peu. J'étais tellement sûr que j'avais compris comment cela fonctionne ...


Il crée simplement une cellule contre avec une queue qui pointe à lui-même.