在阅读了一下之后,似乎Haskell的当前记录情况有点棘手。
例如,StateT
新类型。两个the code
newtype StateT s m a = StateT { runStateT :: s -> m (a,s) }
构造
StateT
runStateT :: s -> m (a, s)
说runStateT
的类型是s -> m (a,s)
。但是,GHCi显示类型确实是
> :t runStateT
runStateT :: StateT s m a -> s -> m (a,s)
这种差异有什么解释吗?记录和函数中的标识符是指两个不同的东西,GHC在幕后神奇地解决了吗?虽然我知道为什么在记录中写s -> m (a,s)
很好,但它似乎错误。
答案 0 :(得分:6)
这实际上是正确的,请记住,记录字段的名称在不同的上下文中意味着两种不同的东西,
GHCi
告诉你函数的含义,但文档正在讨论记录字段本身,而不是它将生成的函数。
基本上在幕后这个
data Foo = Foo {fooy :: Int}
将生成
fooy :: Foo -> Int
fooy Foo{fooy=fooy} = fooy
-- Equivalently: fooy Foo{fooy=bar} = bar
这个函数fooy
就是你在代码中徘徊的东西,但是文档正在谈论记录选择器,我们在代码的Foo{fooy=...}
部分看到了它。
答案 1 :(得分:4)
runStateT
字段的类型为s -> m (a, s)
。 runStateT
字段访问者功能的类型为StateT s m a -> s -> m (a, s)
。
让我们举一个更简单的例子:
data Foo = Bar {foo :: Int}
foo
字段的类型(即可以放入Bar
构造函数的值的类型)只是Int
。
foo
功能的类型为Foo -> Int
。
进一步说明:
Bar {foo = 5}
5显然是Int
。
let x = foo (Bar 5) in ...
此处foo
适用于Bar 5
,其类型为Foo
。因此foo
正在使用Foo
并向我们提供5 - 这是Int
。
答案 2 :(得分:0)
记录的字段 runStateT
类型为s -> m (a,s)
但是(字段访问者)功能,也称为runStateT
类型为StateT s m a -> s -> m (a,s)
,即它返回记录实例的字段值(类型为s -> m (a,s)
)(类型为StateT s m a
)