我们中的许多人没有函数式编程的背景知识,更不用说类别理论代数了.所以我们假设我们需要并因此创建一个类似的泛型类型
data MySomething t = .......
Run Code Online (Sandbox Code Playgroud)
然后我们继续编程,并使用MySomething.什么证据应提醒我们,MySomething是一个单子,那我们必须通过写能使之instance Monad MySomething ...和定义return,并>>=为它?
谢谢.
编辑:另见这个问题:链接操作是monad类解决的唯一问题吗?,这个答案monad是一个带辅助操作的函数数组
我正在阅读Tomas Petricek和Jon Skeet撰写的真实函数式编程书,我很难消化关于计算表达式1)(又名monads)的部分.
通过本书,我了解到 - 与我之前的经验相反 - LINQ查询表达式不仅限于此IEnumerable<T>,而且可以在其他自定义类型上工作.这对我来说似乎很有趣,我想知道是否存在查询表达式语法(from x in ... select ...)非常适合的情况.
显然,这种自定义类型称为计算类型,它们被描绘为与Haskell中的monad基本相同.我从来没有能够理解monad究竟是什么,但根据这本书,它们是通过两个叫做bind和return的操作来定义的.
在函数式编程中,这两个操作的类型签名将是(我认为):
// Bind : M<A'> -> (A' -> B') -> M<B'>
//
// Return : A' -> M<A'>
Run Code Online (Sandbox Code Playgroud)
Mmonadic类型的名称在哪里.
在C#中,这对应于:
Func< M<A>, Func<A,B>, M<B> > Bind;
Func< A, M<A> > Return;
Run Code Online (Sandbox Code Playgroud)
事实证明,LINQ Enumerable.Select(投影运算符)与绑定操作具有完全相同的签名M := IEnumerable.
使用这些知识,我现在可以编写一个不是 的自定义计算类型IEnumerable: …
public static Func<V> To<T, V>(this Func<T> g, Func<T, V> h)
{
return () => h(g());
}
public static Func<T> ToIdentity<T>(this T t)
{
return () => t;
}
Run Code Online (Sandbox Code Playgroud)
在延迟评估时,我有时会使用这些和其他人.这些已经在.net库中吗?
编辑:
以下是一个示例用法:
public static string SuffixColumn(this string v, string suffix, int columns)
{
return
v.ToIdentity()
.ToScrubbedHtml()
.ToFormat(() => "{0} " + suffix.ToLower().PadLeft(columns, ' '))
.ToErrorText(v, suffix, columns)();
}
Run Code Online (Sandbox Code Playgroud)
ToErrorText将'v'检查为合法(非错误代码,非null等),如果好,它运行链接在Func中,如果不好则生成故障安全文本结果.如果v,后缀或列不好,则永远不会调用ToFormat.(因此延迟/未评估的使用).
ToFormat几乎是提供的Func和string.Format的组合.ToIdentity用于将v提升为Func,然后链中的所有内容都基于T的一些Func.
有什么方法可以概括这里的类型定义吗?理想情况下,我希望能够更改'testInput'的类型,并在编译时测试正确推断类型.
public static void Run()
{
var testInput = 3;
var test = ((Func<int, int>) Identity).Compose<int,int,int>(n => n)(testInput);
Console.WriteLine(test);
}
public static Func<T, V> Compose<T, U, V>(this Func<U, V> f, Func<T, U> g)
{
return x => f(g(x));
}
public static T Identity<T> (this T value)
{
return value;
}
Run Code Online (Sandbox Code Playgroud)
更新:我可以指定传递给Compose的函数的类型,但这仍然指定行中的类型.
public static void Run()
{
var testInput = 3;
var identity = (Func<int, int>) Identity;
var test = identity.Compose((int n) => n)(testInput);
Console.WriteLine(test);
}
Run Code Online (Sandbox Code Playgroud)
一点背景; 我正在通过Wes Dyer的The Monvel …
我有一个struct字典,其中一个成员是一个包含适用于每个字典项的不同元素的列表.
我想针对每个项目加入这些元素,以便过滤它们和/或按元素对它们进行分组.
在SQL中我熟悉加入表/查询以获得所需的多行,但我是C#/ Linq的新手.由于"列"可以是已经与正确的字典项关联的对象/列表,我想知道如何使用它们来执行连接?
以下是结构示例:
name elements
item1 list: elementA
item2 list: elementA, elementB
Run Code Online (Sandbox Code Playgroud)
我想要一个提供此输出的查询(count = 3)
name elements
item1 elementA
item2 elementA
item2 elementB
Run Code Online (Sandbox Code Playgroud)
最终,将它们分组为:
element count
ElementA 2
ElementB 1
Run Code Online (Sandbox Code Playgroud)
这是我的代码开始计算字典项目.
public struct MyStruct
{
public string name;
public List<string> elements;
}
private void button1_Click(object sender, EventArgs e)
{
MyStruct myStruct = new MyStruct();
Dictionary<String, MyStruct> dict = new Dictionary<string, MyStruct>();
// Populate 2 items
myStruct.name = "item1";
myStruct.elements = new List<string>();
myStruct.elements.Add("elementA");
dict.Add(myStruct.name, myStruct);
myStruct.name = "item2"; …Run Code Online (Sandbox Code Playgroud) 我有这个功能:
fn folders(dir: &Path) -> Result<Vec<PathBuf>, io::Error> {
fs::read_dir(dir)?
.into_iter()
.map(|x| x.map(|entry| entry.path()))
.collect()
}
Run Code Online (Sandbox Code Playgroud)
其实是从这里借来的。功能正常;不幸的是,我不太明白它是如何工作的。
Ok(["/home/ey/dir-src/9", "/home/ey/dir-src/11", "/home/ey/dir-src/03 A Letter of Explanation.mp3", "/home/ey/dir-src/02 Egyptian Avenue.mp3", "/home/ey/dir-src/alfa", "/home/ey/dir-src/10"])
Run Code Online (Sandbox Code Playgroud)
测试输出显示目录和文件,正如它应该的那样。我不知道在哪里放置文件/目录过滤。我不明白为什么映射里面的映射:它不只是一个简单的路径列表吗?这个表达式中到底发生了什么?
更新:
fn folders(dir: &Path) -> Result<Vec<PathBuf>, io::Error> {
fs::read_dir(dir)?
.into_iter()
.map(|x| x.map(|entry| entry.path()))
.filter(|x| {x.as_ref().map(|entry| entry); true})
.collect()
}
Run Code Online (Sandbox Code Playgroud)
插入一个简单的过滤器(总是true)。它至少正在编译,但我仍然不知道应该如何使用entry文件/目录检查。对不起 :)
public Data GetCurrent(Credentials credentials)
{
var data = new Lazy<Data>(() => GetCurrentInternal(credentials));
try
{
return data.Value;
}
catch (InvalidOperationException ex)
{
throw ex.InnerException;
}
}
Run Code Online (Sandbox Code Playgroud)
如果我将呼叫更改为以下内容:
var data = new Task<Data>(() => GetCurrentInternal(credentials));
Run Code Online (Sandbox Code Playgroud)
有什么变化吗?我宁愿Task过Lazy?怎么样Dispose()和catch(Exception)?
我正在阅读"了解你是一个很好的Haskell!" 并且我对某个代码块的评估的解释感到磕磕绊绊.我已多次阅读这些解释,并开始怀疑即使是作者也能理解这段代码的作用.
ghci> (+) <$> (+3) <*> (*100) $ 5
508
Run Code Online (Sandbox Code Playgroud)
应用程序函数在某些上下文中将函数应用于某个上下文中的值,以在某些上下文中获得某些结果.我花了几个小时来研究这个代码块,并对这个表达式的评估方式提出了一些解释,但没有一个是令人满意的.我知道(5 + 3)+(5*100)是508,但问题是这个表达式.有没有人对这段代码有明确的解释?
什么是编程中的monad,可以解释为:
基本上,我在网上学习中遇到过这个术语.例如,这篇Java 8 Stream教程提到了monads(http://winterbe.com/posts/2014/07/31/java8-stream-tutorial-examples/).所以我想以有用的方式理解基本概念.(与像"想象编程为橙色,然后monads将是葡萄柚......"这样的愚蠢方式相反.)
但是,每个monad教程似乎都需要先前的知识(或试图在运行中教你)Haskell或Haskell语法.
可能重复:
什么是monad?
我正在学习用Haskell的函数式语言编程,在学习解析器时我遇到了Monads.我之前从未听说过这些,所以我做了一些额外的学习,以了解它们是什么.
我为了学习这个主题而无处可见只是让我感到困惑.我真的找不到Monad是什么以及如何使用它们的简单定义."monad是一种根据值和使用这些值计算的序列来计算结构的方法" - 呃???
有人可以提供一个简单的定义Monad在Haskell中的含义,与之相关的法则并给出一个例子吗?