(.) - Function Composition
-- (.) :: (b -> c) -> (a -> b) -> a -> c
> f = (+1)
> g = (*2)
> a = f . g
> a 0
1 -- f( g( 0 ) ) or (0 * 2) + 1
> b = g . f
> b 0
2 -- g( f( 0 ) ) or (0 + 1) * 2
<$> - Functor
-- (<$>) :: Functor f => (a -> b) -> f a -> f b
> a = (*2)
> b = Just 4
> a <$> b
Just 8
<*> - Applicative
-- (<*>) :: Applicative f => f (a -> b) -> f a -> f b
> a = Just (*2)
> b = Just 4
> a <*> b
Just 8
5条答案
按热度按时间0g0grzrc1#
我也在学习Haskell,我的建议是研究一下Learn You a Haskell for Great Good!,更确切地说:
(.)
改为功能组成<$>
和<*>
,请读取应用函子实质上:
(.)
为函数组成:如果有g :: a -> b
和f :: b -> c
,那么f . g
本质上就是f(g(x))
:首先在a
上使用g
获得b
,然后在该b
上使用f
获得c
<$>
接受一个接受a
并返回b
的函数,以及一个包含a
的函子,并且它返回一个包含b
的函子,所以<$>
与fmap :: (a -> b) -> f a -> f b
相同<*>
接受一个函子,这个函子包含一个接受a
并返回b
的函数,以及一个包含a
的函子,它返回一个包含b
的函子,所以<*>
从一个函子中提取函数,并将其应用于一个函子内部的参数,最后将结果返回到函子中注意你在书中章节中找到的解释比我上面的尝试要好
gojuced72#
也许你是通过例子学习的(就像我一样),所以这里有一些简单的例子,你可以在GHCI中随意摆弄。
希望能有所帮助。
umuewwlo3#
(.)
运算符组合函数。例如,\x -> f (g x)
与f . g
相同。您可以对任意函数执行此操作,例如\x -> f (g (h x))
等于f . g . h
。<$>
和<*>
运算符不是根据功能定义的。它们的功能取决于应用它们的实际类型f
。<$>
运算符是Functor
库中fmap
函数的替代。例如,对于Maybe
类型,它取左操作数,并且仅当右操作数是Just
值时才应用它。因此,为了了解这些操作符的作用,只需查看特定类型的实现。rmbxnbpk4#
我是Haskell的新手,有时候Haskell的类型声明也让我很困惑。
一开始很容易迷失方向,因为教程说
Capitalization
命名约定通常用于类型声明,而camelCase
命名约定通常用于变量。实际上,这在Haskell中属于更高级的技术,可能是多态性。只要把
f
,a
和b
看作某种类型变量--处理类型 * 的 * 变量。而Haskell中的class
不是像OOP那样用于Object,而是用于type
。所以Functor f
意味着类型f
属于class Functor
等等。如果你把这些字母
a
,b
,c
替换成某种类型-- * 叫做 *instance
--例如String
Int
Char
。tyky79it5#
虽然
<$>
和<*>
的常见用法被它们在一个类型类中的事实所掩盖,但是你通常可以阅读haddock文档来获得这方面的信息,如果你很难找到一个函数属于哪个模块,可以使用Hoogle。