所以我最近一直在研究monad,我对Haskell编程语言很陌生。
这是我的代码:
for i in range(V):
if len(graph[i]) %2 != 0 :
u = i
break
GHCI编译器显示: 错误:
import Data.List
import System.IO
f :: Int -> (Int, [Char])
f x = (x, ['a'])
g :: Int -> (Int, [Char])
g y = (y, ['b'])
(>>=) :: (Int -> (Int, [Char])) -> (Int -> (Int, [Char])) -> Int -> (Int, [Char])
(>>=) f1 f2 a = f1 (fst (f2 a))
h :: Int -> (Int, [Char])
h x = (>>=) g f x
我做错了什么? 我是否以正确的方式使用monads?
答案 0 :(得分:5)
您正在定义(>>=)
的绑定,该绑定已经被前奏绑定(如上面的注释中所指出的)。
因此,您需要消除对它的每个引用的歧义。
为您的模块命名
module M where
然后,而不是写
h x = (>>=) g f x
使用
h x = (M.>>=) g f x
或
h x = (Prelude.>>=) g f x
选择您想要的>>=
版本。
然而,我认为这不是你真正想做的事情。这个(>>=)
将是一个与Monad
类无关的绑定。
答案 1 :(得分:3)
为了正确回答这个问题,我们必须检查您的假设和实际知识是否与Haskell社区对此知识的定义相匹配。
所以,首先,您显然明白了什么类型,并且您似乎理解多态类型。
因为Monad
是类型类,并且类型类使用多态类型,并且因为类型类也可以使用代数数据类型,所以确保你是个好主意在尝试理解Monad
之前,要对这些事情有一个坚定的理解。类型类与其他语言中的接口非常相似 - 它们定义了一组特定类型类实例必须遵守的强制和可选函数(及其类型)。通常,它们还为您提供“免费”功能以及其他功能的默认定义。他们非常酷:)
有许多好的地方可以让你很好地了解类型类。我会指出你http://www.happylearnhaskelltutorial.com/1/output_other_things.html作为一个简单的介绍(完全披露,我帮助写了这个),以及类词类别,它也将更多地解释Monads(并给你必要的知识){{ 3}}
我还应该提一下,如果你有钱,而你想进行长时间的练习来真正充实你的理解,请查看https://wiki.haskell.org/Typeclassopedia - 它相当冗长,但对你来说可能非常有用,一般来说也是如此让您对Haskell的基础知识有一个很好的理解。
非常重要的是要认识到使用一个Monad
实例之间存在很大差异,其中前奏包含许多常见实例,而正在制作 Monad
实例,这就是您在上面尝试做的事情。
然后,还有Monad
类型类本身的定义,通常在书中作为示例给出,它可以帮助您了解Monad
实例的工作原理。
最终你需要查看Monad
类型类中包含的函数的一般定义,以完全理解它是如何工作的,但是要理解这三个事物是完全独立的,这是很好的。经常被人们互换地描述为“Monad”。 (例如,值Just 5
可以被描述为monadic值,但通常人们只会说它是monad,即使这在技术上是不正确的......因为Maybe
有一个{{ 1}}为其定义的实例,Monad
是Just 5
值。您还可以讨论Maybe
Monad
实例的定义,并查看它是如何实现的,或者甚至自己定义它,只要你确定在尝试通过执行以下操作之一来确定它时不在范围内:隐藏前奏中的默认Maybe
,不要导入前缀,或将Maybe
的其他内容命名为Maybe
。
所以,我建议首先要了解这三件事之间的区别。有了这些知识,请阅读我给你的两个参考资料,然后开始阅读使用类型类的代码,然后阅读一些使用MyMaybe
实例的代码 - 为几种不同的类型提供直觉,然后继续自己重新实现前置Monad
或两个,然后最终尝试创建自己的Monad
类型类的版本而不查看序言,这样您就可以测试自己对函数的理解。然后你会非常了解它们:)
另外值得注意的是,在你到达那里之前,解决类型数最多Monad
的路径可能是一个好主意。无论如何,您可能必须执行此操作,但它们是Monad
,Functor
,最后是Applicative
。您可以选择在Monad
之前添加Semigroup
和Monoid
,但这只是为了让您更多地理解类型类,而不仅仅是理解Functor
类型类的必要条件。