首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Writer monad及其类型声明

Writer monad及其类型声明
EN

Stack Overflow用户
提问于 2022-11-12 10:49:25
回答 1查看 68关注 0票数 0

我正在努力更好地理解Monad,目前我正在研究http://learnyouahaskell.com/for-a-few-monads-more#writer中的写Monad

我不理解似乎由两种类型组成的类型声明,也不理解它的类型约束。

在这些例子中,它们具体说明:

代码语言:javascript
复制
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')  

在实际行动中,它看起来如下:

代码语言:javascript
复制
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) => ...的类型签名中--这可能是因为我在这方面有一些概念上的缺陷。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-11-12 13:02:35

如果将更通用的Writer String替换为更具体的StringWriter,可能会使您感到困惑。

代码语言:javascript
复制
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)

代码语言:javascript
复制
runWriter :: Writer w a -> (a, w)

以及数据构造函数Writer,它将转换为相反的方向:

代码语言:javascript
复制
(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)

以下几点:

类半群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并显式地编写它们:

代码语言:javascript
复制
{-# 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') 
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74412227

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档