组合两个函数以将它们应用于相同的输入

Combining two functions to apply them to the same input

我是 Haskell 的新手,我还在摸索。我正在尝试组合两个函数(Data.Char module in base package) as a first argument to Data.Text.filter 函数中的 isMarkisAlpha。到目前为止我尝试过的是:

import qualified Data.Char as C
import qualified Data.Text as T
import           Data.Text (Text)

strippedInput :: Text -> Text
strippedInput input = T.filter (C.isMark || C.isAlpha) input

哪个不起作用,或者

strippedInput input = T.filter (C.isMark . C.isAlpha) input

但显然它也不起作用,因为 C.isAlpha 的类型是 Char -> Bool 然后成为 C.isMark 的输入,它也是 Char -> Bool 类型所以类型不匹配。

我想在谓词中实现“C.isMark OR C.isAlpha”逻辑,但由于我的知识非常有限,我 运行 不知道如何实现搜索解决方案。

最简单的是使用 lambda 表达式:

strippedInput :: Text -> Text
strippedInput input = T.filter (<b>\x -> C.isMark x || C.isAlpha x</b>) input

您还可以利用函数是应用函子这一事实,从而使用:

import Control.Applicative(liftA2)

strippedInput :: Text -> Text
strippedInput input = T.filter (<b>liftA2 (||) C.isMark C.isAlpha</b>) input

接受的答案是完全正确的。不过,也许我想使用应用运算符;

strippedInput = T.filter $ (||) <$> C.isMark <*> C.isAlpha

但是 liftA2 的问题是,正如名称所描述的那样,它仅硬连接到两个参数函数,是的,这个问题没问题。然而... Haskell 为这项工作提供了更合理的 general 抽象。它基本上被称为函数 monad,通过添加一些实用函数和转换器功能,主要被概括为 Reader monad。但是为了简单起见,我们可以在这里尝试函数 monad。

Function/Reader monad 不仅用于链接两个而且数量不定的函数(每个函数都有两个参数),在这种情况下,第一个参数由前一个函数结果提供,第二个参数由公共读取提供只有状态(在本例中是 input

所以这个问题的答案也可以是

strippedInput = T.filter (C.isMark >>= (\b c -> b || C.isAlpha c) >>= return)

然而,由于 Data.Char 包中充满了 isThisisThat 类型的检查,我们可以展示如何扩展这种方法。

strippedInput = T.filter (C.isMark >>= (\b c -> b || C.isAlpha  c)
                                   >>= (\b c -> b || C.isSymbol c)
                                    .
                                    .
                                   >>= return)

and.. 没有人阻止你做一个比较函数,比如

orWith f      = \b c -> b || f c
strippedInput = T.filter $ C.isMark >>= orWith C.isAlpha
                                    >>= orWith C.isSymbol
                                     .
                                     .
                                    >>= return