Car*_*mey 8 haskell types type-constructor
我之前看过这种类型而不知道它的含义.它是否意味着什么和/或它有名字?
Prelude> :m Data.Functor
Prelude Data.Functor> :t flip . (flip (<$>))
flip . (flip (<$>))
:: Functor ((->) b) => (b -> a) -> b -> (a -> c) -> c
Run Code Online (Sandbox Code Playgroud)
实际上,((->) a)
不是类型而是部分应用的类型构造函数.
就像函数一样,类型构造函数可以部分应用于Haskell.
您可以检查GHCi中的某种东西:
ghci> :k (->)
(->) :: * -> * -> *
ghci> :k (->) Int
(->) Int :: * -> *
Run Code Online (Sandbox Code Playgroud)
所有价值观都有类型 *
; 类型构造有各种样* -> *
,* -> * -> *
等等.
在Haskell,(->) a
来自a -> something
.请记住,您可以使用parans将操作符转换为带前缀的函数.即(+) 1 1 == 2
.所以在这种情况下,"operator"是类型构造函数->
.它是以这种方式使用的,因为仿函数需要一个带有1个变量的类型构造函数,但是它->
有2.所以我们部分应用它.
它可以帮助你认识到,<$>
对于((->) a)
仅仅是(.)
要添加到Matt Fenwick和josefg的更多技术答案,((->) a
可以将其视为形成依赖于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 = ...
Run Code Online (Sandbox Code Playgroud)
((->) 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
Run Code Online (Sandbox Code Playgroud)
应用<*>
操作为您提供同时性:
-- The joint membership of team1 and team2, depending on the Day:
(++) <$> membership team1 <*> membership team2 :: Historical Day [Person]
Run Code Online (Sandbox Code Playgroud)
实际上,既然我们有,instance Monoid [a]
并且instance Monoid m => Monoid t -> m
,前面的例子可以像这样写:
import Data.Monoid
membership team1 ++ membership team2
Run Code Online (Sandbox Code Playgroud)
Monad为您提供作文:
personToManager :: Person -> Historical Day Manager
personToManager = ...
managerToVP :: Manager -> Historical Day VP
managerToVP = ...
personToVP :: Person -> Historical Day VP
personToVP p = personToManager p >>= managerToVP
Run Code Online (Sandbox Code Playgroud)
另请注意,((->) r
这与Reader r
monad 完全相同.如果你理解上面的代码,你几乎可以理解Reader
.
编辑:我应该澄清,时间相关的值只是函数/ Reader monad的一个用途.还有其他用途; Reader monad的经典示例用例是通过计算来线程化配置值.正如上面的例子所显示的那样,它有更多的用途.
归档时间: |
|
查看次数: |
331 次 |
最近记录: |