LoginSignup
0
1

More than 5 years have passed since last update.

PureScript by Example の 7.1, 7.2, 7.3, 7.4 を読む

Last updated at Posted at 2016-12-24

この記事は (bouzuya) PureScript Advent Calendar 2016 の 24 日目。 (bouzuya) PureScript Advent Calendar 2016 は bouzuya の PureScript 学習の記録だ。

概要

PureScript by ExamplePureScript Language GuidePursuit を見ながら進めていく。

今日は 7.1, 7.2, 7.3, 7.4 を読む。ソースコードの例は purescript-book の exercises/chapter7 にある。

※注意事項: 英語と日本語訳では大きな差異がある。0.10.x に対応している英語の側で進める。

PureScript by Example 7.1

この章では applicative functor と traversable functor が出て来るらしい。例としては 3 章の電話帳をまた使うらしい。

Pursuit:

PureScript by Example 7.2

purescript-controlpurescript-validation を使うらしい。

Pursuit:

PureScript by Example 7.3

例の通りに説明してみる。

下記のような address があるとき、 Maybe をとる形で使いたくなることはままある。

address :: String -> String -> String -> AddressBook

Maybe をとる形は次のような型になりそうだ。

address' :: Maybe String -> Maybe String -> Maybe String -> Maybe AddressBook

これを実装するには Control.Apply モジュールの lift3 を使うと良いらしい。

lift3 :: forall a b c d f. Apply f => (a -> b -> c -> d) -> f a -> f b -> f c -> f d

Pursuit:

Maybe ではなく Apply だけど、MaybeApply のインスタンスなので問題ない。

Pursuit:

> import Control.Apply (lift3)
> import Data.AddressBook (address)
> import Data.Maybe (Maybe(..))
> :t lift3
forall a b c d f. (Apply f) => (a -> b -> c -> d) -> f a -> f b -> f c -> f d

> :t address
String -> String -> String -> Address

> :t (lift3 address)
forall t1. (Apply t1) => t1 String -> t1 String -> t1 String -> t1 Address

> lift3 address (Just "123 Fake St.") Nothing (Just "CA")
Nothing

> lift3 address (Just "123 Fake St.") (Just "Faketown") (Just "CA")
(Just Address { street: "123 Fake St.", city: "Faketown", state: "CA" })

ふむ。ひとつでも Nothing だと Nothing になる。

PureScript by Example 7.4

lift3 :: forall a b c d f. Apply f => (a -> b -> c -> d) -> f a -> f b -> f c -> f d

で出てくる Apply って何なの、という話。

class Functor f where
  map :: forall a b. (a -> b) -> f a -> f b

class Functor f <= Apply f where
  apply :: forall a b. f (a -> b) -> f a -> f b

f の中にない関数を f の中の a に適用する map と、f の中にある関数を f の中の a に適用する applyf は今回だと Maybe

instance functorMaybe :: Functor Maybe where
  map f (Just a) = Just (f a)
  map f Nothing  = Nothing

instance applyMaybe :: Apply Maybe where
  apply (Just f) (Just x) = Just (f x)
  apply _        _        = Nothing

さきの例から想像できる範囲の実装。

lift3 の実装。それぞれ map<$>apply<*> という operator が使われている。

forall a b c d f. (Apply f) => (a -> b -> c -> d) -> f a -> f b -> f c -> f d
lift3 f x y z = f <$> x <*> y <*> z

順番に追っていけば確かに。

> import Data.AddressBook (address)
> import Data.Maybe (Maybe(..))
> import Prelude ((<$>), (<*>))
> address <$> Just "123 Fake St." <*> Nothing <*> Just "CA"
Nothing

> address <$> Just "123 Fake St." <*> Just "Faketown" <*> Just "CA"
(Just Address { street: "123 Fake St.", city: "Faketown", state: "CA" })

まとめ

簡単に Maybe 対応できちゃうもんだなあ……。 Functormap って聞くと戸惑うけど、JavaScript でも Arraymap 使ってるんだよな……。

次回以降の TODO

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1