結論
Getting (First a) s a
はMaybe a
を返せるようなPrism' s a
の特殊化だから。
(Getting (First a) s a
はPrism' s a
)
(^?)とは?
Prism
のアクセサです。
ちょうどLens
の(^.)
と同じですが、Prism
なのでMaybe
で結果を返します。
(^?) :: s -> Getting (First a) s a -> Maybe a
このようなPrismを作った時に使います。
Test.hs
{-# LANGUAGE TemplateHaskell #-}
module Test
( Foo(..)
, _Bar
, _Baz
) where
import Control.Lens (makePrisms)
data Foo = Bar Int
| Baz Char
makePrisms ''Foo
-- 以下の関数がコンパイル時に定義される
-- _Bar :: (Choice p, Applicative f) => p Int (f Int) -> p Foo (f Foo)
-- _Baz :: (Choice p, Applicative f) => p Char (f Char) -> p Foo (f Foo)
Main.hs
import Test
import Control.Lens ((^?))
x :: Foo
x = Bar 10
y :: Foo
y = Baz 'a'
main :: IO ()
main = do
print $ x ^? _Bar
print $ x ^? _Baz
print $ y ^? _Bar
print $ y ^? _Baz
output
Just 10
Nothing
Nothing
Just 'a'
Prism
はこんな型です。
type Prism s t a b = forall p f. (Choice p, Applicative f) => p a (f b) -> p s (f t)
-- _Bar :: (Choice p, Applicative f) => p Int (f Int) -> p Foo (f Foo)
-- _Baz :: (Choice p, Applicative f) => p Char (f Char) -> p Foo (f Foo)
しかしPrism
のアクセサである(^?)
は、
Prism s t a b
ではなくGetting (First a) s a
を要求します。
type Getting r s a = (a -> Const r a) -> s -> Const r s
結論
やはりGetter
, Getting
、Setter
, Setting
の時と同じで、Getting (First a) s a
はPrism s t a b
として一般化できます。
type Prism s t a b = forall p f. (Choice p, Applicative f) => p a (f b) -> p s (f t)
type Getting r s a = (a -> Const r a) -> s -> Const r s
なぜなら……
(->)
はChoice
なのでp
に当てはまります。
instance Choice (->)
First a
はMonoid
で、かつConst (First r)
はApplicative
なので、
Const (First a)
がf
に当てはまります。
instance Monoid (First a)
instance Monoid a => Applicative (Const a)
(First a
はMaybe a
と同型です)
これを簡約すると
Getting (First a) s a = (a -> Const (First a) a) -> s -> Const (First a) s
(Const (First a)を一般化) ==> forall f. Applicative f => (a -> f a) -> s -> f s
((->)を一般化) ==> forall p f. (Choice p, Applicative f) => p a (f a) -> p s (f s)
= Prism s s a a
(s,aを一般化) ==> Prism s t a b
となるので、Prism s t a b
はGetting (First a) s a
の一般化です。
それによりGetting (First a) s a
はPrism s s a a
になるので、
(^?)
はより特殊化された型Getting (First a) s a
を受け取ります。
(特殊化することによりMaybe a
を返せるようにしてるはず)
Prism s s a a
はPrism' s a
なので、上述の結論に帰着します。
1,2ヶ月前にlensを使い始めたときからの疑問だったのですが、わかってしまえば最強ですね。
よっしゃ