【发布时间】:2017-07-21 12:00:30
【问题描述】:
我正在用 C# 编写一个链接列表程序,因为我想测试我对这门语言的感受,但我遇到了一些严重的困难。我正在尝试实现一个 Map 方法,该方法的功能类似于 Haskell 映射函数(两者的代码如下)。但是,我收到了错误消息:
main.cs(43,66): error CS0029: Cannot implicitly convert type `void' to `MainClass.LinkedList<U>'
main.cs(43,33): error CS1662: Cannot convert `lambda expression' to delegate type `System.Func<MainClass.LinkedList<U>>' because some of the return types in the block are not implicitly convertible to the delegate return type
有问题的相关代码: 理想的 Haskell 代码:
map :: [a] -> (a -> b) -> [b]
map (x:[]) f = (f x) : []
map (x:xs) f = (f x) : (map xs f)
C#代码:
public class LinkedList<T> where T: class
{
public T first;
public LinkedList<T> rest;
public LinkedList(T x) {this.first = x;}
public void Join(LinkedList<T> xs)
{
Do(this.rest, ()=>this.rest.Join(xs), ()=>Assign(ref this.rest, xs));
}
public LinkedList<U> Map<U>(Func<T, U> f) where U: class
{
return DoR(this.rest, ()=>new LinkedList<U>(f(this.first)).Join(this.rest.Map(f)), ()=>new LinkedList<U>(f(this.first)));
}
public static void Assign<T>(ref T a, T b)
{
a = b;
}
public static U DoR<T, U>(T x, Func<U> f, Func<U> g)
{
if (x!=null) {return f();}
else {return g();}
}
public static void Do<T>(T x, Action f, Action g)
{
if (x != null) {f();}
else {g();}
}
虽然 Assign、DoR(Do 和 Return 的缩写)和 Do 看起来像是“代码味道”,但它们是我试图不写的原因
if (x != null) {f();}
else {g();}
type 语句(我习惯于模式匹配)。如果有人有更好的想法,我很想知道他们,但主要是我关心突出的问题。
【问题讨论】:
-
看起来您正在尝试将 C# 用作函数式语言。虽然委托等使这成为可能,但这并不是 C# 的主要使用方式。如果你想要一种函数式编程 .Net 语言,你看过 F# 吗?
-
你需要让
Join返回结果LinkedList。或者更改您传递给DoR的lambda,以在变量中捕获LinkedList,然后在其上调用Join,最后返回它。 -
在我看来,您所做的事情“没有抓住 C# 的重点”。如果存在 C# 的 List 对象,这些都不是必需的。
-
@itsme86 更多的是我不喜欢一遍又一遍地输入相同的东西(如果你在谈论静态方法)。虽然我确实从函数式语言中学到了这些技术,但我不相信这个程序是函数式的,事实上它对我来说似乎非常不实用(因为有很多副作用)。有什么可以代替 if(x!=null) {f();} else {g();} 的推荐吗?
-
为什么
LinkedList<T>中的T有class约束?看来Map可以简单写成return new LinkedList<U>(f(first)) { rest = this.rest == null ? null : this.rest.Map(f) }
标签: c# lambda functional-programming