Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 如何阅读蒙纳恐惧症并询问其定义?_Haskell - Fatal编程技术网

Haskell 如何阅读蒙纳恐惧症并询问其定义?

Haskell 如何阅读蒙纳恐惧症并询问其定义?,haskell,Haskell,我试图弄明白,如何阅读下面的类类型定义: Prelude Data.Functor.Identity Control.Monad.Reader> :i ask class Monad m => MonadReader r (m :: * -> *) | m -> r where ask :: m r ... m是一种更高级的类型,它必须是monad 但是m->r意味着什么呢 尝试按以下方式播放ask: Prelude Data.Functor.Identity

我试图弄明白,如何阅读下面的类类型定义:

Prelude Data.Functor.Identity Control.Monad.Reader> :i ask
class Monad m => MonadReader r (m :: * -> *) | m -> r where
  ask :: m r
  ...
m
是一种更高级的类型,它必须是
monad

但是
m->r
意味着什么呢

尝试按以下方式播放
ask

Prelude Data.Functor.Identity Control.Monad.Reader> ask "Hello"
"Hello"
为什么我可以将参数传递给
ask
?查看类型签名:

ask :: m r

我无法认识到,我可以将一个参数传递给
ask

m->r
是一个函数依赖项,它粗略地说明,当试图选择要使用的
monawarder
实例时,知道
m
就足以知道
r
。换句话说,不能用相同的
m
定义两个不同的
r
实例

现在,为了确定使用
ask
的哪个定义,我们转向类型推断。从它的定义中,我们知道
ask
的类型是
monaderrm=>mr
。从它在
ask“Hello”
中的使用,我们知道它还必须有一个类似
a->b
的类型;更具体地说,我们知道
a
String
相统一,因为这是
的类型“Hello”
。因此,我们的任务是将
monaderrm=>mr
String->b
统一起来

这很简单。在前缀符号中重写
String->b
,并使用显式括号,我们可以将它们排列在一起:

MonadReader r m => m             r
                   ((->) String) b
所以
m~(-)字符串)
r~b
(尽管我们仍然不知道
r/b
应该是什么)。查看可用的
monawarder
,我们发现
m-String
(或者更一般地说,
(>)r
)的(唯一)实例:

现在我们知道,对于选择
m
ask=id
。(这让我们也可以看到
r~b~字符串

因此,
询问“Hello”==id“Hello”==“Hello”

请注意,
ask
不一定是一个函数。它也可能是
Reader ra
类型的值,在这种情况下,必须使用
runReader
来提取函数

> :t runReader ask
runReader ask :: a -> a
> runReader ask "Hello"
"Hello"
它也可能是一个更复杂的monad,涉及
ReaderT

> :t runReaderT ask
runReaderT ask :: Monad m => a -> m a
> runReaderT ask "Hello" :: Maybe String
Just "Hello"
> runReaderT ask "Hello" :: Either String String
Right "Hello"

我认为这个想法是,当你试图调用
字符串
上的
ask
时,类型推断允许
m
与函数monad统一,因此你最终得到
ask::String->String
m->r
是一个函数依赖项;知道
m
就足以推断出
r
是什么。本质上,它说,你不能为同一个monad定义多个
monader
实例,但是使用不同的
r
s。我不知道如何给出详细的答案,但简而言之:
m->r
是一个问题。函数本身就是一个Monad实例,所以当你问“Hello”
时,Haskell会选择这个Monad。(事实上,这只是阅读器Monad本身。)我也不理解
ask::monaderrm=>mr
类型签名。为什么类型签名包含
=>
?这意味着什么?它意味着
ask
是任何monad
m
和类型
r
的类型
m
的值,其中有一个
monawarder
实例。这是否意味着类型
r
的monad实例?不,
r
是monad
m
所“包装”的类型。大多数情况下,
monawarder
的实例(粗略地说)是函数、
Reader
(本身只是函数的包装器),或者是使用
ReaderT
构建的monad。这意味着
ask
几乎总是一个值,或者可以从中提取函数。
> :t runReaderT ask
runReaderT ask :: Monad m => a -> m a
> runReaderT ask "Hello" :: Maybe String
Just "Hello"
> runReaderT ask "Hello" :: Either String String
Right "Hello"