我之前看过这种类型而不知道它意味着什么。这是否意味着什么? 和/或它有名字吗?
Prelude> :m Data.Functor
Prelude Data.Functor> :t flip . (flip (<$>))
flip . (flip (<$>))
:: Functor ((->) b) => (b -> a) -> b -> (a -> c) -> c
答案 0 :(得分:9)
实际上,((->) a)
不是类型,而是部分应用的类型构造函数。
就像函数一样,类型构造函数可以在Haskell中部分应用。
您可以查看GHCi中种类的内容:
ghci> :k (->)
(->) :: * -> * -> *
ghci> :k (->) Int
(->) Int :: * -> *
所有值都有types of kind *
;类型构造函数有* -> *
,* -> * -> *
等类型
答案 1 :(得分:5)
在Haskell中,(->) a
来自a -> something
。请记住,您可以使用parans将操作符转换为带前缀的函数。即(+) 1 1 == 2
。所以在这种情况下,“operator”是类型构造函数->
。它是以这种方式使用的,因为仿函数需要一个带有1个变量的类型构造函数,但->
有2个。所以我们部分应用它。
可能会让您意识到<$>
的{{1}}只是((->) a)
答案 2 :(得分:5)
要添加到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
,这意味着类型类操作可用,并且与{{1}一起使用时它们具有非常有用的解释}}
第一个例子:Historical t
将函数应用于与时间相关的值。例如,
fmap
Applicative -- The number of persons in a Team, depending on the Day:
membershipCount :: Team -> Historical Day Int
membershipCount = fmap length . membership
操作为您提供 simultaneousity :
<*>
实际上,由于我们有-- 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
Monad为您提供作文:
import Data.Monoid
membership team1 ++ membership team2
另请注意,personToManager :: Person -> Historical Day Manager
personToManager = ...
managerToVP :: Manager -> Historical Day VP
managerToVP = ...
personToVP :: Person -> Historical Day VP
personToVP p = personToManager p >>= managerToVP
与((->) r
monad完全相同。如果您理解上面的代码,那么您非常了解Reader r
。
编辑:我应该澄清时间相关的值只是函数/ Reader monad的一次使用。还有其他用途; Reader monad的经典示例用例是通过计算来线程化配置值。正如上面的例子所示,它有更多的用途,而不仅如此。