Haskell:了解应用函子的纯函数

cen*_*980 1 haskell functional-programming applicative

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

pure :: a -> f a 
Run Code Online (Sandbox Code Playgroud)

我知道pure函数可以接受任何类型的值,并返回其中包含该值的适用值。因此,如果应用实例为Maybe,则pure 3给出Just 3

但是,当您将纯值应用到应用值中已经包含的值时会发生什么?例如,如果您做类似的事情会怎样pure Just 3

bra*_*drn 9

如果将纯值应用于已经在应用值内的值,会发生什么?

它只是包裹在一个附加层中。最终结果是一个嵌套在另一个应用程序值内的应用程序值。

例如,如果您做类似的事情会怎样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)
    
    Run Code Online (Sandbox Code Playgroud)

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

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

    …除了事实证明可以进行类型检查!因此,我们缺少了一些东西。在这种情况下,事实证明有一个函数的应用实例:

    instance Applicative ((->) r) where
      pure x = \r -> x
      (<*>) = _irrelevant_here
    
    Run Code Online (Sandbox Code Playgroud)

    语法有点有趣,但是它基本上意味着它r -> ...是可应用的。这个特定的实例称为Reader monad,它被广泛使用。(有关此特定数据类型的更多信息,请参见此处此处。)这个想法是r -> a可以计算a给定的r输入;例如,在这种情况下,pure x创建一个忽略其输入并x始终返回的函数,并将输入f <*> x提供给和,然后将r两者合并。在这种情况下,我们仅使用,因此手工评估很容易:fxpure(pure Just) 3

    (pure Just) 3
    = (\r -> Just) 3
    = Just
    
    Run Code Online (Sandbox Code Playgroud)

    因此,这里的想法是pure包装Just一个应用值,在这种情况下恰好是一个函数;然后,我们将此功能应用于3,从而摆脱了包装程序,从而揭示了原始内容Just


Dam*_*ero 5

首先, pure 有以下类型:

pure :: Applicative f => a -> f a
Run Code Online (Sandbox Code Playgroud)

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

:k f 
f :: * -> *
Run Code Online (Sandbox Code Playgroud)

和那种a*

那么 , 的类型a就是a, any a,是所有类型中最多态的(但*请记住)。所以你并不真正关心 a 的值,你只是有一个限制,那就是typeclassApplicative,以及那种f(记住* -> *

所以在这种情况下:

gchi> pure 3 :: Maybe Int
ghci> Just 3
Run Code Online (Sandbox Code Playgroud)

fMaybe并且a3

以同样的方式

gchi> pure $ Just 3 :: Maybe (Maybe Int)
gchi> Just (Just 3)
Run Code Online (Sandbox Code Playgroud)

这里f再次MaybeaJust 3

您可以稍微将类型更改为纯:

gchi> pure 3 :: [Double]
ghci> [3.0]
Run Code Online (Sandbox Code Playgroud)

在这里,f是 [],并且a3

同样的方法

ghci> pure [3] :: [[Double]]
ghci> [[3.0]]
Run Code Online (Sandbox Code Playgroud)

终于f又来了,现在[]a现在 [3]