2011-09-19 4 views
1

J'ai du mal à implémenter une monade peut-être - que j'ai appelé Nullable dans cet exemple.Objets imbriqués Nullable et la monade Peut-être

La classe Nullable est mis en œuvre comme suit:

Public NotInheritable Class Nullable(Of TClass) 

    Private _value As TClass 
    Private _hasValue As Boolean 

    Public Shared Function Create(ByVal value As TClass) As Nullable(Of TClass) 
     Return New Nullable(Of TClass)(value) 
    End Function 
    Public Shared Function Create() As Nullable(Of TClass) 
     Return New Nullable(Of TClass)() 
    End Function 

    Private Sub New() 
     HasValue = False 
    End Sub 
    Private Sub New(theValue As TClass) 
     Value = theValue 
     HasValue = True 
    End Sub 

    Public Property Value() As TClass 
     Get 
      Return _value 
     End Get 
     Private Set(value As TClass) 
      _value = value 
     End Set 
    End Property 

    Public Property HasValue() As Boolean 
     Get 
      Return _hasValue 
     End Get 
     Private Set(value As Boolean) 
      _hasValue = value 
     End Set 
    End Property 

End Class 

Il y a une classe parente mis en œuvre comme

Class Parent 
    Public Property ChildClass as Nullable(Of Child) 
End Class 

et une classe enfant est tout simplement

Class Child 
    Public Property ID as String 
    ... other properties below ... 
End Class 

La façon dont la monade est mis en œuvre au moment où je aurais besoin de publier ce qui suit pour accéder à une propriété sur le enfant STED classe

dim id = MyParentClass.ChildClass.Value.ID 

mais idéalement ce que je voudrais être en mesure de faire est d'avoir fait la déclaration suivante

dim id = MyParentClass.ChildClass.Id 

et si le ChildClass est nul alors que renvoyer une valeur par défaut de la propriété type.

J'ai essayé de l'implémenter en utilisant les propriétés par défaut et en définissant la valeur par défaut via un attribut mais il ne serait pas compilé.

Est-ce que cela sera possible ou peut-être y a-t-il une meilleure façon de l'architecturer - ou peut-être que je n'ai pas la monade?

De nombreux ZCI

Simon

Répondre

2

Eh bien, la définition de Maybe lui-même est tout simplement une valeur unique qui peut ou non être présent, de sorte que beaucoup est très bien. Incidemment, si vous n'aimez pas le nom "Peut-être" pour une raison quelconque, je suggère de considérer "Option" au lieu de "Nullable", puisque Nullable est déjà utilisé par .NET (dans le même but, mais seulement avec les types de valeur), tandis que Option est ce que F # appelle et la cohérence est agréable. De toute façon, il y a essentiellement deux choses que vous pouvez faire avec une telle valeur - appliquer une transformation à la valeur (s'il y en a une), et réduire les couches imbriquées (par exemple, transformer un nullable d'un "foo" en juste un nullable de "foo"). Vous pouvez faire tout le reste étant donné ceux-ci et la capacité de construire de nouvelles valeurs. L'opération "transform" est implémentée plus simplement en prenant un lambda (comparez la méthode Select utilisée par LINQ - c'est la même chose), et soit en l'appliquant à la valeur encapsulée soit en la supprimant s'il n'y a pas de valeur. L'opération "effondrement" est assez simple; il suffit de garder la valeur interne si elle existe. LINQ est une approche très naturelle ici - vous pouvez penser à Maybe comme représentant une séquence énumérable d'au plus un élément. Cela dit, vous ne voulez probablement pas utiliser lambdas ou des expressions LINQ partout dans le monde. La mauvaise nouvelle est que je ne pense pas qu'il y ait un autre moyen.

Ce que je pense que vous vraiment voulez ici est d'appliquer l'opération « transformer » en utilisant implicitement la syntaxe d'appel de méthode régulière, tout en appliquant automatiquement l'opération « effondrement » si la méthode renvoie aussi quelque chose annulable, et peut-être fournir une valeur par défaut lorsque vous essayez d'utiliser une valeur manquante directement.C'est un design raisonnable, et très pratique à utiliser, mais je ne pense pas que ce soit possible ici (j'ai essayé quelques variantes en utilisant C#, et je ne pense pas que VB.NET soit assez différent pour aider). Le résultat final d'un tel schéma est la possibilité d'appeler des méthodes sur des valeurs NULL et de récupérer une valeur nulle au lieu d'une exception de référence NULL. A titre d'exemple, here's something similar in Ruby, implémenté avec un peu de supercherie de métaprogrammation que je ne pense pas que VB.NET puisse supporter. Je me rappelle vaguement avoir vu des idées similaires en Javascript et dans d'autres langues. En bref, je pense que vous avez fondamentalement la bonne idée, mais ce que vous essayez d'accomplir malheureusement n'est pas possible.

+0

+1 Merci beaucoup pour votre réponse. Simon –