尝试在Haskell中定义自定义绑定运算符时出错

时间:2017-06-24 21:29:13

标签: haskell module scope functional-programming monads

所以我最近一直在研究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?

2 个答案:

答案 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}}为其定义的实例,MonadJust 5值。您还可以讨论Maybe Monad实例的定义,并查看它是如何实现的,或者甚至自己定义它,只要你确定在尝试通过执行以下操作之一来确定它时不在范围内:隐藏前奏中的默认Maybe,不要导入前缀,或将Maybe的其他内容命名为Maybe

所以,我建议首先要了解这三件事之间的区别。有了这些知识,请阅读我给你的两个参考资料,然后开始阅读使用类型类的代码,然后阅读一些使用MyMaybe实例的代码 - 为几种不同的类型提供直觉,然后继续自己重新实现前置Monad或两个,然后最终尝试创建自己的Monad类型类的版本而不查看序言,这样您就可以测试自己对函数的理解。然后你会非常了解它们:)

另外值得注意的是,在你到达那里之前,解决类型数最多Monad的路径可能是一个好主意。无论如何,您可能必须执行此操作,但它们是MonadFunctor,最后是Applicative。您可以选择在Monad之前添加SemigroupMonoid,但这只是为了让您更多地理解类型类,而不仅仅是理解Functor类型类的必要条件。

祝你好运!