代码之家  ›  专栏  ›  技术社区  ›  kaqqao

理解读者单子

  •  13
  • kaqqao  · 技术社区  · 7 年前

    PureScript示例 接着是介绍读者monad的部分。示例如下:

    createUser :: Reader Permissions (Maybe User)
    createUser = do
      permissions <- ask
      if hasPermission "admin" permissions
        then map Just newUser
        else pure Nothing
    

    让我困惑的是 ask

    ask   :: forall r. Reader r r
    

    它似乎是凭空创造了一个读者

    State get 作用文本解释如下:

    我猜这是关键,同样的事情也发生在读者身上,但我不明白它是如何工作的。。。

    当通过运行上述示例时 runReader ? Haskell文档 检索monad环境。 从哪里来 ? 在我看来,一个值被传递给 runReader ,存储 ,为了得到它-你打电话

    虽然这个例子是PureScript,但我猜想任何懂Haskell的人都能够回答,因此Haskell标签。

    3 回复  |  直到 5 年前
        1
  •  13
  •   Mark Seemann    7 年前

    A. 读者 Reader r r ,你真的只能从 r r r -> r .

    可以 凭空召唤函数,因为如果你是柏拉图主义者,我想它们总是存在的。。。

    当您使用 do r r 价值,以及当您使用 <- arrow,你只需要了解这个背景。

        2
  •  3
  •   Regis Kuckaertz    6 年前

    你可以通过执行一些替换来说服自己它是有效的。首先看签名 createUser Reader :

    createUser :: Reader Permissions (Maybe User)
    {- definition of Reader -}
    createUser :: ReaderT Permissions Identity (Maybe User)
    

    ReaderT 类型只有一个数据构造函数: ReaderT (r -> m a) ,这意味着 是一个计算为类型值的项 ReaderT (Permissions -> Identity (Maybe User)) . 如您所见,它只是一个带有 . 它不必凭空创建任何内容,但将接收类型的值 Permissions

    do 符号只是句法上的糖,表达式:

    do permissions <- ask
       if hasPermission "admin" permissions
         then map Just newUser
         else pure Nothing
    

    ask >>= \permissions -> 
      if hasPermission "admin" permissions
      then map Just newUser
      else pure Nothing
    

    ask , >>= pure 对于 ReaderT公司

    ask >>= \permissions -> ...
    {- definition of ask for ReaderT -}
    ReaderT pure >>= \permissions -> ...
    {- definition of >>= for ReaderT -}
    ReaderT \r ->
      pure r >>= \a -> case (\permissions -> ...) a of ReaderT f -> f r
    {- function application -}
    ReaderT \r ->
      pure r >>= \a -> 
        case (if hasPermission "admin" a
              then map Just newUser
              else pure Nothing) of ReaderT f -> f r
    {- definition of pure for Identity -}
    ReaderT \r ->
      Identity r >>= \a -> 
        case (if hasPermission "admin" a
              then map Just newUser
              else pure Nothing) of ReaderT f -> f r
    {- definition of >>= for Identity -}
    ReaderT \r ->
      (\a -> 
        case (if hasPermission "admin" a
              then map Just newUser
              else pure Nothing) of ReaderT f -> f r) r
    {- function application -}
    ReaderT \r ->
      case (if hasPermission "admin" r
            then map Just newUser
            else pure Nothing) of ReaderT f -> f r
    

    正如你所见, 创建用户 显然只是一个由 在表达式中穿插一个值(“环境”)。 runReader 展开函数并使用提供的参数调用它:

    runReader :: forall r a. Reader r a -> r -> a
    runReader (ReaderT f) r = f r
    
        3
  •  0
  •   Tom Huntington    2 年前

    (->) r 是函子,即。 r->a 是任何类型的容器 a (a) List a Bool->a ) . 此外,它也是单子

    instance Monad ((->) r) where
        f >>= k = \ r -> k (f r) r
    

    MonadReader 类型类,称为简单读取器单子,可能被赋予类型同义词 Reader r .

    ask 返回此单子 (->) r) r r ,然后我们可以绑定它。

    了解部分函数类型 (>)r 较好的