我正在努力更好地理解Monad,目前我正在研究http://learnyouahaskell.com/for-a-few-monads-more#writer中的写Monad
我不理解似乎由两种类型组成的类型声明,也不理解它的类型约束。
在这些例子中,它们具体说明:
newtype Writer w a = Writer { runWriter :: (a, w) }
instance (Monoid w) => Monad (Writer w) where
return x = Writer (x, mempty)
(Writer (x,v)) >>= f = let (Writer (y, v')) = f x in Writer (y, v `mappend` v') 在实际行动中,它看起来如下:
ghci> runWriter (return 3 :: Writer String Int)
(3,"")
ghci> runWriter (return 3 :: Writer (Sum Int) Int)
(3,Sum {getSum = 0})
ghci> runWriter (return 3 :: Writer (Product Int) Int)
(3,Product {getProduct = 1}) 但我想知道,为什么它返回的是Writer String Int而不是这些元素的元组呢?
我能做一个Monad类型(例如Writer2)来返回Writer String Int Float吗?
此外,它使我感到困惑,为什么实例化只使用(Monoid w) => Monad (Writer w)而不是(Monoid w a) => Monad (Writer w a)。为什么Monad绑定和返回方法中没有列出w,比如a将包含在类型约束(Num a) => ...的类型签名中--这可能是因为我在这方面有一些概念上的缺陷。
发布于 2022-11-12 13:02:35
如果将更通用的Writer String替换为更具体的StringWriter,可能会使您感到困惑。
newtype StringWriter a = StringWriter (a, String)
instance Monad StringWriter where
return x = StringWriter (x, "")
(StringWriter (x, v)) >>= f = let (StringWriter (y, v')) = f x
in StringWriter (y, v ++ v')但我想知道,为什么它返回的是
而不是这些元素的元组呢?
Writer String Int只是表示元组(Int, String)的另一种方式。查看runWriter的签名,它将从Writer String Int转换为(Int, String)
runWriter :: Writer w a -> (a, w)以及数据构造函数Writer,它将转换为相反的方向:
(a, w) -> Writer w a,我能做一个Monad类型(例如,
Writer2)来返回Writer String Int Float吗?
我不太清楚这是什么意思,但是对于monad来说,它必须适用于所有类型,所以在声明monad实例时,a in StringWriter a是很重要的。(令人困惑的是,您需要它,但不要编写它:instance Monad StringWriter。)
此外,
使我感到困惑,为什么实例化只需要
(Monoid w) => Monad (Writer w)而不是(Monoid w a) => Monad (Writer w a)。
以下几点:
Monoid w a没有意义,因为Monoid typeclass只有一个参数:类半群a =>幺半群a,其中
Monad (Writer w a)没有意义,因为Monad typeclass的参数不是类型,而是类型构造函数(只有一个参数)。这与采用具体类型(而不是一个参数的类型构造函数)的Monoid类型形成了对比。也就是说,instance Monad StringWriter是正确的,但instance Monad (StringWriter Int)不是。请注意,StringWriter Int是一个类型,但StringWriter是一个带有一个参数的类型构造函数。以及为什么Monad绑定和
return方法中没有列出w,比如a将包含在类型约束(Num a) => ...的类型签名中
它没有列出,因为函数类型声明没有列出。您可以启用InstanceSigs extension并显式地编写它们:
{-# LANGUAGE InstanceSigs #-}
instance (Monoid w) => Monad (Writer w) where
return :: (Monoid w) => a -> Writer w a
return x = Writer (x, mempty)
(>>=) :: (Monoid w) => Writer w a -> (a -> Writer w b) -> Writer w b
(Writer (x,v)) >>= f = let (Writer (y, v')) = f x
in Writer (y, v `mappend` v') https://stackoverflow.com/questions/74412227
复制相似问题