记录字段的类型不一致

时间:2014-02-25 16:13:35

标签: haskell record

在阅读了一下之后,似乎Haskell的当前记录情况有点棘手。

例如,StateT新类型。两个the code

newtype StateT s m a = StateT { runStateT :: s -> m (a,s) }

the docs

  

构造

     

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)很好,但它似乎错误

3 个答案:

答案 0 :(得分:6)

这实际上是正确的,请记住,记录字段的名称在不同的上下文中意味着两种不同的东西,

  1. 一个函数,从它所处的值的类型到单个字段。
  2. 可用于模式匹配和构造的神奇记录字段
  3. 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