有人可以解释一下这段代码中应用实例是在哪里出现的吗?

发布于 2024-12-29 01:59:59 字数 188 浏览 5 评论 0原文

isAlphaNum :: Char -> Bool
isAlphaNum = (||) <$> isAlpha <*> isNum 

我可以看到它有效,但我不明白 Applicative (或 Functor)的实例来自哪里。

isAlphaNum :: Char -> Bool
isAlphaNum = (||) <
gt; isAlpha <*> isNum 

I can see that it works, but I don't understand where the instances of Applicative (or Functor) come from.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

听闻余生 2025-01-05 01:59:59

这是((->) r)Applicative 实例,来自常见类型的函数。它通过复制单个参数以用于所有函数,将具有相同第一个参数类型的函数组合成单个函数。 (<$>) 是函数组合,pure 是 const(<*>) 翻译为

s :: (r -> a -> b) -> (r -> a) -> r -> b
s f g x = f x (g x)

:函数可能更广为人知的是S 组合器

((->) r) 函子也是 Reader monad,其中共享参数是“环境”值,例如:

newtype Reader r a = Reader (r -> a)

我不会说它是 <为了使函数成为无点的,这样做很常见,但在某些情况下,一旦您习惯了这种用法,它实际上可以提高清晰度。例如,你给出的例子,我可以很容易地理解为“是一个字符,一个字母或数字”。

This is the Applicative instance for ((->) r), functions from a common type. It combines functions with the same first argument type into a single function by duplicating a single argument to use for all of them. (<$>) is function composition, pure is const, and here's what (<*>) translates to:

s :: (r -> a -> b) -> (r -> a) -> r -> b
s f g x = f x (g x)

This function is perhaps better known as the S combinator.

The ((->) r) functor is also the Reader monad, where the shared argument is the "environment" value, e.g.:

newtype Reader r a = Reader (r -> a)

I wouldn't say it's common to do this for the sake of making functions point-free, but in some cases it can actually improve clarity once you're used to the idiom. The example you gave, for instance, I can read very easily as meaning "is a character a letter or number".

孤檠 2025-01-05 01:59:59

您可以从 Control.Applicative 包中免费获得所谓的静态箭头的实例(请参阅 Conor McBride 等人的“Applicative Planning with Effects”)。因此,在您的情况下,任何源类型 Char 都会产生一个 Applicative 实例,其中任何其他类型 a 都映射到类型 Char ->;一个。

当您组合其中任何一个时,假设应用一个函数 f :: Char ->一个-> b 为值 x :: Char -> a,语义是你创建一个新函数Char -> b,它将像这样将其参数输入到 fx 中,

f <*> x = \c -> (f c) (x c)

因此,正如您所指出的,这使得您的示例相当于

isAlphaNum c = (isAlpha c) || (isNum c)

在我看来,这种努力并不总是必要的,如果 Haskell 对应用程序有更好的语法支持(也许类似于 2 级语言),看起来会更好。

You get instances of what are called static arrows (see "Applicative Programming with Effects" by Conor McBride et al.) for free from the Control.Applicative package. So, any source type, in your case Char, gives rise to an Applicative instance where any other type a is mapped to the type Char -> a.

When you combine any of these, say apply a function f :: Char -> a -> b to a value x :: Char -> a, the semantic is that you create a new function Char -> b, which will feed its argument into both f and x like so,

f <*> x = \c -> (f c) (x c)

Hence, as you point out, this makes your example equivalent to

isAlphaNum c = (isAlpha c) || (isNum c)

In my opinion, such effort is not always necessary, and it would look nicer if Haskell had better syntactic support for applicatives (maybe something like 2-level languages).

迷路的信 2025-01-05 01:59:59

应该注意的是,通过使用 lift 函数,您可以获得类似的效果,例如:

import Data.Char
import Control.Applicative 

isAlphaNum = liftA2 (||) isAlpha isNumber

或者,使用 ((->) r) 的 monad 实例而不是应用实例:

import Data.Char
import Control.Monad 

isAlphaNum = liftM2 (||) isAlpha isNumber

[Digression]

现在如果您知道如何将一个参数分配给两个中间函数并将结果分配给二元函数,则存在某种相关的情况,您想要分配两个< /em> 一个 中间函数的参数并将结果发送到二进制函数:

import Data.Function

orFst = (||) `on` fst

-- orFst (True,3) (False, 7)
--> True

例如,此模式经常用于比较函数。

It should be noted that you get a similar effect by using the lift functions, e.g.:

import Data.Char
import Control.Applicative 

isAlphaNum = liftA2 (||) isAlpha isNumber

Or, using the monad instance of ((->) r) instead of the applicative one:

import Data.Char
import Control.Monad 

isAlphaNum = liftM2 (||) isAlpha isNumber

[Digression]

Now that you know how to distribute one argument to two intermediate functions and the result to a binary function, there is the somehow related case that you want to distribute two arguments to one intermediate function and the results to a binary function:

import Data.Function

orFst = (||) `on` fst

-- orFst (True,3) (False, 7)
--> True

This pattern is e.g. often used for the compare function.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文