我正在定义一个monad的实例,如下所示:
data Something = Something a
instance Monad Something where
return a = Something a --Wraps a in 'Something', correct?
m >>= f = do
var <- m
return $ f var --I want this to pass var to f, then wrap the result
--back up in the 'Something' monad with the return I
--Just defined
Run Code Online (Sandbox Code Playgroud)
问题是 - >
1:我在做什么有明显的错误/误解吗?
2:Haskell会知道调用我上面定义的返回 m >>= f
3:如果由于某种原因我定义了另一个功能
f :: Something a -> Something b
f x = do
var <- x
return $ doMagicTo x
Run Code Online (Sandbox Code Playgroud)
将return调用我在monad实例中定义的返回并将x包装进去Something?
Joh*_*n L 16
这里有一些大问题.
首先,一个Monad实例必须有种类 * -> *.这意味着他们至少需要一个类型变量,而你Something没有任何变量.为了比较:
-- kind * -> *
Maybe
IO
Either String
-- kind *
Maybe Int
IO ()
Either String Double
Run Code Online (Sandbox Code Playgroud)
看到每一个Maybe,IO以及Either String需要一个类型参数,然后才能使用它们?有了Something,没有地方可以填写类型参数.所以你需要将你的定义更改为:
data Something a = Something a
Run Code Online (Sandbox Code Playgroud)
第二个大问题是>>=你的Monad实例中的错误.你通常不能使用do-notation,因为它只调用Monad函数return和>>=.所以你必须在没有任何monad函数的情况下写出来,无论是do-notation还是call >>=或者return.
instance Monad Something where
return a = Something a --Wraps a in 'Something'
(Something m) >>= f = f m --unwraps m and applies it to f
Run Code Online (Sandbox Code Playgroud)
定义>>=比您预期的简单.展开m很容易,因为你只需要在Something构造函数上进行模式匹配.另外f :: a -> m b,所以你不必担心再把它包起来,因为f这样做对你而言.
虽然一般没有办法打开monad ,但很多特定的 monad都可以打开.
请注意,使用do-notation或>>=monad实例声明在语法上没有任何错误.问题是以>>=递归方式定义,因此当您尝试使用它时,程序会进入无限循环.
(Something这里定义的NB 是Identity monad)
对于第三个问题,是returnMonad实例中定义的函数是将被调用的函数.类型按类型调度,并且如您所指定的那样,类型必须是Something b编译器将自动使用Monad实例Something.(我想你的意思是最后一行doMagicTo var).
主要问题是你的定义>>=是循环的.
Haskell的做语法是链语法糖>>=和>>,让您的定义
m >>= f = do
var <- m
return $ f var
Run Code Online (Sandbox Code Playgroud)
Desugars来
m >>= f =
m >>= \var ->
return $ f var
Run Code Online (Sandbox Code Playgroud)
所以你定义m >>= f为m >>= \...,这是循环的.
您需要做的>>=是定义如何从m中提取值以传递给f.另外,你f应该返回一个monadic值,所以return在这里使用是错误的(这更接近你定义的方式fmap).
>>=for 的定义Something可以是:
(Something a) >>= f = f a
Run Code Online (Sandbox Code Playgroud)
这是身份Monad - 有很多关于它的文章 - 它是了解monad如何工作的一个很好的起点.