函数类型为MonadReader

时间:2018-05-09 18:10:50

标签: haskell

我正在浏览lens tutorial,特别是试图绕过view中涉及的类型。

所以,采取定义

data Atom = Atom { _element :: String, _point :: Point }
data Point = Point { _x :: Double, _y :: Double }
makeLenses ''Atom
makeLenses ''Point

让我们检查表达式view (point . x)的类型:

*Main> :t view (point . x)
view (point . x) :: MonadReader Atom m => m Double

因此,给定一个Atom的环境,我们可以生成一个Double包裹在MonadReader中。很好,这比镜头新手所期望的更为通用!

现在,让我们尝试将其应用于某些atom

*Main> :t view (point . x) (Atom "C" (Point 1 2))
view (point . x) (Atom "C" (Point 1 2)) :: Double

这种类型检查如何给出view (point . x)的上述类型?我知道部分应用的函数类型MonadReader有一个r ->的实例,但ghc如何能够确定在这种情况下应该使用这个特定的实例(如果那样的话)当然,确实使用了一个吗?

1 个答案:

答案 0 :(得分:4)

关键是您使用了 application 的语法。

写作时

view (point . x) (Atom "C" (Point 1 2))

您实际上是在f af = view (point . x)编写应用a = Atom "C" (Point 1 2)。要键入check f a GHC最初从

开始
f :: t1 -> t2     -- in prefix for rm, this is written as (->) t1 t2
a :: t1

对于一些新的类型变量t1, t2。这始终适用于所有应用程序。 (好吧,差不多。一些高级类型需要更仔细的算法,但我忽略了这一点。)

然而,GHC也知道

f :: MonadReader Atom m => m Double
a :: Atom

因此它推断出t1 ~ Atomm ~ (->) t1 ~ (->) Atom。由于这确实是一个MonadRead Atom实例,因此它继续进行。