このタイプは、意味を知らずに見たことがあります。それは何かを意味していますか、および/または名前がありますか?
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 :: * -> *
すべての値には kind の型があり *
ます。* -> *
型コンストラクタには、* -> * -> *
、 などの種類があります。
Haskell では、(->) a
からa -> something
. parans を使用して、演算子を接頭辞付き関数に変えることができることに注意してください。すなわち(+) 1 1 == 2
。したがって、この場合、「演算子」は型コンストラクター->
です。ファンクターは 1 つの変数を持つ型コンストラクターを必要としますが、->
2 つあるため、このように使用されます。したがって、部分的に適用します。
<$>
for((->) a)
がちょうどであることを理解するのに役立つかもしれません(.)
Matt Fenwick と josefg のより技術的な回答に追加すると、 は、((->) a
に依存する値を形成する型コンストラクターとして読み取ることができますa
。1 つの例: 時間の経過とともにメンバーシップが変化するチームがあるとします。これを表す 1 つの可能な方法は、次のようになります。
-- | 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
モナドはあなたに構成を与えます:
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
ます。
編集:時間依存の値は、関数/Reader モナドの1 つの使用にすぎないことを明確にする必要があります。他にも用途があります。Reader モナドの古典的なユースケースの例は、計算を通して構成値をスレッド化することです。上記の例が示すように、それ以外にもさまざまな用途があります。