可嵌套的嵌套对象和可能的Monad

时间:2011-09-19 10:59:04

标签: vb.net monads

我正在努力实现一个monad - 在这个例子中我称之为Nullable。

Nullable Class实现如下:

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

有一个实现为

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

和儿童类只是

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

目前实现monad的方式我需要发出以下内容来访问嵌套子类的属性

dim id = MyParentClass.ChildClass.Value.ID

但理想情况下,我希望能够做的是拥有以下声明

dim id = MyParentClass.ChildClass.Id

如果ChildClass为null,则只返回属性类型的默认值。

我尝试使用默认属性实现此功能,并通过属性将值设置为默认值,但不会编译。

这是可能的,还是有更好的方法来构建它 - 或者我可能没有'得到'可能的monad?

许多TIA

西蒙

1 个答案:

答案 0 :(得分:2)

嗯,Maybe本身的定义只是一个可能存在或不存在的单个值,所以很好。顺便提一下,如果由于某种原因你不喜欢名字“Maybe”,我建议考虑“Option”而不是“Nullable”,因为.NET已经使用Nullable(出于同样的目的,甚至 - 但只有值类型),而Option是F#调用它并且一致性很好。

无论如何,使用这样的值基本上可以做两件事 - 将变换应用于值(如果有的话),并折叠嵌套层(例如,将可为空的“foo”变成可为空的只是一个可以被称为“foo”的人。你可以做其他所有的事情以及构建新价值的能力。

“转换”操作最简单的方法是使用lambda(比较LINQ使用的Select方法 - 它是相同的东西),并将其应用于包装值或丢弃它(如果有)没有价值。 “崩溃”操作非常简单;只要保持内在价值(如果存在)。 LINQ在这里是一种非常自然的方法 - 您可以将Maybe视为表示最多一个元素的可枚举序列。

那就是说,你可能不想在任何地方使用lambdas或LINQ表达式。坏消息是我认为没有其他办法。

我怀疑你真正想要的是使用常规方法调用语法隐式应用“transform”操作,同时如果方法也返回可以为空的东西,则自动应用“collapse”操作,并且可能尝试直接使用缺失值时提供默认值。这是一个合理的设计,并且非常方便使用,但我认为这不可能(我自己尝试了一些使用C#的变体,我认为VB.NET不足以提供帮助)。这样的方案的最终结果是能够在空值上调用方法,并返回空值而不是空引用异常。作为一个例子,here's something similar in Ruby,实现了一些我认为VB.NET不能支持的元编程技巧。我隐约记得在Javascript和其他一些语言中看到类似的想法。

简而言之,我认为你基本上是正确的想法,但你想要完成的事情是不可能的。