我正在尝试学习更多关于函数式编程的知识,使用language.ext(C#)库作为起点。我正在尝试使用一个Either monad,但有一些我想念的东西。请参阅一个简单的例子:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Dates
{
public class AssignmentDate
{
public static Either<string, AssignmentDate> Create(DateTime date)
{
if (date < MinValue)
return Left<string, AssignmentDate>("date out of range");
return Right<string, AssignmentDate>(date);
}
public static DateTime MinValue => new DateTime(1950, 1, 1);
}
}
类型Left&lt;&gt;和对&lt;&gt;无法解决。我显然错过了什么,但是什么?我使用的是Either&lt;&gt;是否正确?这是使用Either&lt;&gt ;?时返回的正确方法吗?任何人都可以指出更多的language.ext示例吗?非常感谢您提供的任何帮助。
答案 0 :(得分:3)
我失踪了 - “使用静态LanguageExt.Prelude;”不知道为什么,但Visual Studio对此有点不同,我在对象浏览器中找不到任何对Left或Right的引用。
答案 1 :(得分:3)
我是Language-Ext的作者。 Left
和Right
是构造函数,而不是它们自己的类型,它们都构造了Either<L, R>
。许多类型在静态类Prelude
中都有构造函数,这就是为什么需要对它进行using static
的原因。它不是命名空间而是类。
您可以写下:Prelude.Left<L, R>(...)
和Prelude.Right<L, R>(...)
。
这是为了模拟像F#这样的函数式语言中的代数数据类型(ADT),Either
可以这样定义:
type Either<'l, 'r> =
| Left of l
| Right of r
允许您像Either
那样构建Right(x)
。
其他构造函数有:Some(x)
None
和Option
List(x,y,z)
,Lst
为Set(x,y,x)
,Set
为Prelude
,等。
using static
类可以很容易地将一大堆基本功能包含在一个using static LanguageExt.Either
中,而不必包含using static LanguageExt.Option
,public static Either<string, AssignmentDate> Create(DateTime date) =>
date < MinValue
? Left<string, AssignmentDate>("date out of range")
: Right<string, AssignmentDate>(date);
等。
顺便说一下,编写示例的更实用的方法是:
from /home/user/.rvm/rubies/ruby-2.2.4/lib/ruby/site_ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require'
原因是三元运算符是一个表达式,而您使用多个语句来获取结果。如果您正在学习函数式编程,那么您应该尽可能地尝试使用表达式。例外情况是您需要声明局部变量,但大多数情况下您可以在C#中使用纯表达式。如果表达式太大,请将它们分解为更小的函数。函数式编程的一个副作用是你的函数会变得越来越小;有时只有单行事务。