我以前见过这种类型但不知道它的意思。它代表了什么意思,或者有一个名字吗?
Prelude> :m Data.Functor
Prelude Data.Functor> :t flip . (flip (<$>))
flip . (flip (<$>))
:: Functor ((->) b) => (b -> a) -> b -> (a -> c) -> c
我以前见过这种类型但不知道它的意思。它代表了什么意思,或者有一个名字吗?
Prelude> :m Data.Functor
Prelude Data.Functor> :t flip . (flip (<$>))
flip . (flip (<$>))
:: Functor ((->) b) => (b -> a) -> b -> (a -> c) -> c
实际上,((->) a)
不是一种类型,而是一个部分应用的类型构造器。
就像函数一样,在Haskell中可以部分应用类型构造器。
您可以在GHCi中检查某些东西的种类:
ghci> :k (->)
(->) :: * -> * -> *
ghci> :k (->) Int
(->) Int :: * -> *
*
;类型构造器具有像* -> *
,* -> * -> *
等类型。*
的类型。 - Daniel Wagner(->) a
来自 a -> something
。请记住,您可以通过使用括号将运算符转换为前缀函数。例如 (+) 1 1 == 2
。因此,在这种情况下,“运算符”是类型构造器 ->
。它以这种方式使用,因为函子需要一个具有1个变量的类型构造器,但是->
有2个变量。所以我们部分应用它。((->) a)
,<$>
就是 (.)
。((->) a)
的类型是 *->*
? - Carlos López-Camey(->)
的种类为 * -> * -> *
,而 (->) a
的种类为 * -> *
。 - Jon Purdy((->) a)
不是一种类型!但是如果你把/type/换成/kind/,那就正确了。 - Matt Fenwick除了Matt Fenwick和josefg的更技术性的答案之外,((->) a
可以被理解为构造一个依赖于a
的值的类型构造器。 举个例子:假设你有一些会员组,在不同的时间里会员可能会变化。 一种可能的表示方法是这样的:
-- | The type of a's that depend on a point in time, using t as the timeline type.
type Historical t a = t -> a
observe :: Historical t a -> t -> a
observe = ($)
-- | The membership of a team is a list of persons whose composition can change
-- from day to day.
membership :: Team -> Historical Day [Person]
membership = ...
((->) a)
"是一个函子(Functor)、应用函子(Applicative)和单子(Monad),这意味着可以使用类型类操作,并且在与Historical t
一起使用时具有非常有用的解释。fmap
将函数应用于时间相关的值。例如,-- The number of persons in a Team, depending on the Day:
membershipCount :: Team -> Historical Day Int
membershipCount = fmap length . membership
Applicative <*>
操作可以让你实现同时性:
-- The joint membership of team1 and team2, depending on the Day:
(++) <$> membership team1 <*> membership team2 :: Historical Day [Person]
实际上,由于我们有 instance Monoid [a]
和 instance Monoid m => Monoid t -> m
,前面的例子可以这样写:
import Data.Monoid
membership team1 ++ membership team2
Monad 给你提供了组合的能力:
personToManager :: Person -> Historical Day Manager
personToManager = ...
managerToVP :: Manager -> Historical Day VP
managerToVP = ...
personToVP :: Person -> Historical Day VP
personToVP p = personToManager p >>= managerToVP
((->) r
与 Reader r
单子是完全相同的。如果你理解了上面的代码,你就基本上理解了 Reader
。
(->) a b
与a -> b
是相同的。 - Vitus(3+)
而不是((+) 3)
,那么你可以将((->) a)
看作(a ->)
- 尽管这不是有效的语法,但它可以让你了解它的含义。 - AndrewC