Haskell 理解作者类型

Haskell 理解作者类型,haskell,syntax,functional-programming,monads,record,Haskell,Syntax,Functional Programming,Monads,Record,我在《给你学哈斯卡尔好东西》一书中了解了单子米兰·利波瓦卡。我正在阅读Control.Monad.Writer模块如何导出Writer w a类型及其Monad实例和一些用于处理此类型值的有用函数 对于以下代码: newtype Writer w a = Writer { runWriter :: (a,w) } 我知道atype参数表示某个值的类型,wtype参数表示附加的幺半群值的类型。通过将w和a传递给Writer类型构造函数,您可以得到一个Writer单子作为回报,而这个单子只有一个函

我在《给你学哈斯卡尔好东西》一书中了解了单子米兰·利波瓦卡。我正在阅读Control.Monad.Writer模块如何导出
Writer w a
类型及其Monad实例和一些用于处理此类型值的有用函数

对于以下代码:

newtype Writer w a = Writer { runWriter :: (a,w) }
我知道
a
type参数表示某个值的类型,
w
type参数表示附加的幺半群值的类型。通过将
w
a
传递给
Writer
类型构造函数,您可以得到一个Writer单子作为回报,而这个单子只有一个函数,即
runWriter
函数,这是对的吗

在这本书中,它说
runWriter
函数获取一个包装在
Writer
newtype中的元组并将其展开,返回一个简单的元组。但是
runWriter
的类型声明是
runWriter::(a,w)
,它不接受任何参数作为输入。
runWriter
如何获取用newtype包装的元组并只返回一个简单的元组

通过将
w
a
传递给Writer类型构造函数,您可以得到Writer monad作为回报,这是正确的吗

否,
Writer w
是monad(假设
Monoid w
)<代码>编写器w a是一种类型

这个单子只有一个函数,那就是
runWriter
函数

不,类型
Writer wa
本质上是成对类型
(a,w)
。里面没有函数

您可以假设该类型是按以下方式定义的

newtype Writer w a = Writer (a,w)
还有一个单独的方便的“展开”功能

您可以将这些函数视为相互反转:

Writer :: (a,w) -> Writer w a        -- "wrapper"
runWriter :: Writer w a -> (a,w)     -- "unwrapper"
使用
data
声明中的记录语法确实定义了采用隐式参数的函数(除了数据类型本身)。 任何类型

定义数据类型
T
、数据构造函数
MkT
、函数
f
、具有隐式
T
参数的
g

f :: T -> Int               -- f (MkT i _) = i
g :: T -> String            -- g (MkT _ s) = s

使用
newtype
s录制语法的工作方式相同,只是必须只有一个字段(在您的示例中名为
runWriter

对于您的示例,runWriter(Writer p)=p,我说Writer p是monad是正确的吗?那么本质上runWriter(Writer p)=p将取出monad中的任何内容?还有,你怎么知道Writer wa是成对类型的呢?任何见解都值得赞赏。@ceno980
Writer p
是一个值,因此它不能是monad,这是类型级别的东西。我们可以说,
Writer p
是一个“一元值”,即对于某些单子
m
a
类型,是
ma
类型的值。
runWriter
提取
Writer
包装下的内容是正确的
Writer wa
本质上是一对,因为它是这样定义的:如果我们把
newtype T=T{runT::a}
放在一起,那么类型
T
a
本质上是相同的——它们只是名称不同而已。您可以将
x::A
转换为
tx::T
,然后将
y::T
转换为
runT y::A
,而不会丢失信息。如果您以
newtype Writer w A=MkWriter(A,w)
的形式编写,则不会将数据(
MkWriter p
)与类型(
Writer w A
)混淆@ceno980@chi对于此行:data T=MkT{f::Int,g::String}。基本上,数据类型T有一个值构造函数MkT,它有两个字段f和g,分别是Int和String类型。为了创建一个值为Int/String的字段,必须将数据类型本身(T)传递给函数f/g以获取值?这对吗?@ceno980不太对。我们可以构造
T
值,如
x=mkt1“a”
;我们可以用
fx==1
gx==“b”
处理这些值。但是,我们也可以使用记录语法来创建值,比如
x=MkT{g=“a”,f=1}
。然后是记录更新语法
y=x{f=2}
data T = MkT { f :: Int, g :: String }
f :: T -> Int               -- f (MkT i _) = i
g :: T -> String            -- g (MkT _ s) = s