【问题标题】:Haskell: Understanding the pure function for Applicative functorsHaskell:理解应用函子的纯函数
【发布时间】:2019-07-19 02:00:28
【问题描述】:

我正在学习 Applicative Functors,纯函数具有以下类型声明:

pure :: a -> f a 

我知道纯函数接受任何类型的值并返回一个应用值,其中包含该值。所以如果应用实例是Maybepure 3 会给出Just 3

但是,当您将 pure 应用于已在应用值内的值时会发生什么?例如。如果您执行pure Just 3 之类的操作会发生什么?

【问题讨论】:

  • 如果您区分pure Just 3pure (Just 3),您可能会发现结果更容易理解。
  • 你的意思是:(pure (Just 3)) :: Maybe (Maybe Integer) == Just (Just 3)?
  • FWIW, Just 可以被认为是一个带有签名a -> Maybe a 的函数。

标签: haskell functional-programming applicative


【解决方案1】:

当您将 pure 应用于已在应用值内的值时会发生什么?

它只是被包裹在一个额外的层中。最终结果是嵌套在另一个应用值中的应用值。

例如如果您执行pure Just 3 之类的操作会发生什么?

这是一个有趣的问题,尽管可能不是出于您的意思。这里重要的一点是区分pure (Just 3)——这可能是你的意思——和pure Just 3 = (pure Just) 3,这是你写的。这给出了两种情况:

  • pure (Just 3) 只是将pure 应用于值Just 3,正如我上面讨论的那样,它给出了Just (Just 3),这是一个嵌套的应用值。
  • (pure Just) 3 是一个有趣的案例。回忆pureJust的类型:

    pure :: Applicative f => a -> f a
    Just :: a -> Maybe a
    -- so:
    pure Just :: Applicative f => f (a -> Maybe a)
    

    换句话说,pure Just 采用函数 Just 并将其包装在一个应用值中。

    接下来,我们要将pure Just 应用于值3。但我们不能这样做,因为f (a -> Maybe a) 是一个值,而不是一个函数!所以(pure Just) 3 应该会导致类型错误。

    ...但事实证明类型检查很好!所以我们错过了一些东西。在这种情况下,事实证明有一个函数的应用实例:

    instance Applicative ((->) r) where
      pure x = \r -> x
      (<*>) = _irrelevant_here
    

    语法有点搞笑,但基本上意味着r -&gt; ... 是一个应用程序。这个特殊的实例被称为 Reader monad,它的使用非常广泛。 (有关此特定数据类型的更多信息,请参见例如herehere。)这个想法是r -&gt; a 可以在给定r 输入的情况下计算a;在这种情况下,pure x 创建一个忽略其输入并始终返回x 的函数,f &lt;*&gt; xr 输入提供给ff,然后将两者结合起来。在这种情况下,我们只使用pure,因此很容易手动评估(pure Just) 3

    (pure Just) 3
    = (\r -> Just) 3
    = Just
    

    所以这里的想法是pureJust 包装在一个应用值中,在这种情况下恰好是一个函数;然后,我们将此函数应用于3,它去掉了包装以显示原始的Just

【讨论】:

    【解决方案2】:

    首先,pure 有类型:

    pure :: Applicative f => a -> f a
    

    为了让事情更简单,想想f的那种

    :k f 
    f :: * -> *
    

    a 的类型是*

    那么a 的类型就是a,任何a,是最多态的(但请记住*)。所以你并不真正关心 a 的值,你只是有一个限制,那就是 typeclass Applicative 和 f 的那种(记住 * -&gt; *

    所以在这种情况下:

    gchi> pure 3 :: Maybe Int
    ghci> Just 3
    

    这里fMaybea3

    同理

    gchi> pure $ Just 3 :: Maybe (Maybe Int)
    gchi> Just (Just 3)
    

    这里f 又是MaybeaJust 3

    你可以玩一点改变类型为纯:

    gchi> pure 3 :: [Double]
    ghci> [3.0]
    

    这里,f 是 [],a3

    同样的方式

    ghci> pure [3] :: [[Double]]
    ghci> [[3.0]]
    

    终于到了,f 又是 []a 是 [3]

    【讨论】:

      猜你喜欢
      • 2016-03-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-18
      • 1970-01-01
      • 2019-11-10
      相关资源
      最近更新 更多