Haskell 有人能解释一下应用程序实例在代码中的位置吗? isAlphaNum::Char->Bool isAlphaNum=(| |)isAlpha isNum
我可以看出它是有效的,但我不明白Haskell 有人能解释一下应用程序实例在代码中的位置吗? isAlphaNum::Char->Bool isAlphaNum=(| |)isAlpha isNum,haskell,functor,applicative,Haskell,Functor,Applicative,我可以看出它是有效的,但我不明白Applicative(或Functor)的实例来自哪里。这是((->)r)的Applicative实例,函数来自一个普通类型。它通过复制单个参数以用于所有函数,将具有相同第一个参数类型的函数合并为单个函数()是函数组合,pure是常量,下面是()的意思: isAlphaNum :: Char -> Bool isAlphaNum = (||) <$> isAlpha <*> isNum 这个函数最好称为 ((->)r)函子也是读
Applicative
(或Functor
)的实例来自哪里。这是((->)r
)的Applicative
实例,函数来自一个普通类型。它通过复制单个参数以用于所有函数,将具有相同第一个参数类型的函数合并为单个函数()
是函数组合,pure是常量,下面是()
的意思:
isAlphaNum :: Char -> Bool
isAlphaNum = (||) <$> isAlpha <*> isNum
这个函数最好称为
((->)r)
函子也是读取器
单子,其中共享参数是“环境”值,例如:
s :: (r -> a -> b) -> (r -> a) -> r -> b
s f g x = f x (g x)
我不会说为了使函数无点而这样做是很常见的,但在某些情况下,一旦你习惯了这个习惯用法,它实际上可以提高清晰度。例如,您给出的示例,我可以很容易地理解为“是一个字符,一个字母或数字”。您可以从
控件.Applicative
包中免费获得所谓静态箭头的实例(请参阅Conor McBride等人的“带效果的应用程序编程”)。因此,任何源类型(在您的例子中为Char
)都会产生一个应用实例,其中任何其他类型a
都映射到类型Char->a
当您组合其中任何一个函数时,比如将一个函数f::Char->a->b
应用于一个值x::Char->a
,语义是您创建一个新函数Char->b
,它将把它的参数输入到f
和x
中,就像这样
newtype Reader r a = Reader (r -> a)
在我看来,这样的努力并不总是必要的,如果Haskell对应用程序有更好的语法支持(可能类似于两级语言),它看起来会更好。应该注意的是,使用提升函数可以获得类似的效果,例如:
isAlphaNum c = (isAlpha c) || (isNum c)
或者,使用((->)r的monad实例而不是应用程序实例:
import Data.Char
import Control.Applicative
isAlphaNum = liftA2 (||) isAlpha isNumber
[题外话]
既然您知道了如何将一个参数分配给两个中间函数,并将结果分配给一个二进制函数,那么有一种情况与此相关,即您希望将两个参数分配给一个中间函数,并将结果分配给一个二进制函数:
import Data.Char
import Control.Monad
isAlphaNum = liftM2 (||) isAlpha isNumber
此模式通常用于
比较
功能 还有Control.Concatenative
,它将一些标准的连接组合词引入Haskell。您的示例可以是bi-isAlpha-isNumber(| |)
和fst`biAp`(| |)
。这里不一定要显示,但是控制。串联式确实有助于提高许多无点表达式的易读性,因为这就是串联式编程的全部内容。isAlphaNum
=(\c->(((| |)isAlpha)c(isNum c))
=(\c->isAlpha c | | isNum c)
(…只是旁注)。
import Data.Char
import Control.Monad
isAlphaNum = liftM2 (||) isAlpha isNumber
import Data.Function
orFst = (||) `on` fst
-- orFst (True,3) (False, 7)
--> True