実例によるPureScript 7 章

Applicative の章。難易度が上がって来ている気がする。演習はなんとかこなせたが、正直まだ全然適切に利用できる気がしない。慣れるものなんだろうか。

1. (簡単)lift2を使って、オプショナルな引数に対して働く、数に対する演算子+、-、*、/の持ち上げられたバージョンを書いてください。

main :: Effect Unit
main = do
  logShow $ lift2 (+) (Just 2) (Just 3)
  logShow $ lift2 (+) (Just 2) Nothing
  logShow $ lift2 (-) (Just 2) (Just 3)
  logShow $ lift2 (-) (Just 2) Nothing
  logShow $ lift2 (*) (Just 2) (Just 3)
  logShow $ lift2 (*) (Just 2) Nothing
  logShow $ lift2 (/) (Just 6) (Just 3)
  logShow $ lift2 (/) (Just 2) Nothing
(Just 5)
Nothing
(Just -1)
Nothing
(Just 6)
Nothing
(Just 2)
Nothing


2.  (やや難しい) 上で与えられたlift3の定義について、<$>と<*>の型が整合していることを確認して下さい。

難しいが、lift3 は

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

となっているので、最初の <$> が適用された状態では、コンテナ内で残り 2 引数待ち状態になる。

f (b -> c -> d) -> f b -> f c -> f d

<*> で f b、f c を渡せば f d が返ってくるので整合している、、で説明になっているのか??

3. (難しい) 次の型を持つ関数combineMaybeを書いてください。

combineMaybe : forall a f. (Applicative f) => Maybe (f a) -> f (Maybe a)
この関数は副作用をもつオプショナルな計算をとり、オプショナルな結果をもつ副作用のある計算を返します。

combineMaybe :: forall a f. (Applicative f) => Maybe (f a) -> f (Maybe a)
combineMaybe Nothing = pure Nothing
combineMaybe (Just x) = (pure Just) <*> x


1. (簡単) 正規表現の検証器を使って、Address型のstateフィールドが2文字のアルファベットであることを確かめてください。ヒント:phoneNumberRegexのソースコードを参照してみましょう。

validateState :: String -> V Errors String
validateState state = matches "State" stateRegex state

stateRegex :: Regex
stateRegex = unsafeRegex "^\\w{2}$" noFlags


2. (やや難しい)matches検証器を使って、文字列に全く空白が含まれないことを検証する検証関数を​​書いてください。この関数を使って、適切な場合にnonEmptyを置き換えてください。

validateNoSpace :: String -> String -> V Errors String
validateNoSpace field = matches field noSpaceRegex

noSpaceRegex :: Regex
noSpaceRegex = unsafeRegex "^(?!.* ).*$" noFlags


1. (やや難しい) 左から右へと副作用を連鎖させる、次のような二分木データ構造についてのTraversableインスタンスを書いてください。

data Tree a = Leaf | Branch (Tree a) a (Tree a)
これは木の走査の順序に対応しています。行きがけ順の走査についてはどうでしょうか。帰りがけ順では?

3. (難しい)traverseを使ってsequenceを書いてみましょう。また、sequenceを使ってtraverseを書けるでしょうか?

data Tree a = Leaf | Branch (Tree a) a (Tree a)

instance showTree :: Show a => Show (Tree a) where
  show Leaf = "<Leaf>"
  show (Branch tl a tr) = "<" <> show tl <> ", " <> show a <> ", " <> show tr <> ">"

instance functorTree :: Functor Tree where
  map _ Leaf = Leaf
  map f (Branch tl a tr) = Branch (map f tl) (f a) (map f tr)

instance fodableTree :: Foldable Tree where
  foldr _ init Leaf = init
  foldr func init (Branch tl a tr) = foldr func (func a (foldr func init tr)) tl
  foldl _ init Leaf = init
  foldl func init (Branch tl a tr) = foldl func (func (foldl func init tl) a) tr
  foldMap _ Leaf = mempty
  foldMap func (Branch tl a tr) = (foldMap func tl) <> (func a) <> (foldMap func tr)

instance treeTraverse :: Traversable Tree where
  traverse _ Leaf = pure Leaf
  traverse func (Branch tl a tr) = Branch <$> traverse func tl <*> func a <*> traverse func tr
  sequence = traverse identity
  --sequence Leaf = pure Leaf
  --sequence (Branch tl a tr) = Branch <$> sequence tl <*> a <*> sequence tr


2. (やや難しい)Data.Maybeを使ってPersonのaddressフィールドを省略可能になるようにコードを変更してください。ヒント:traverseを使って型Maybe aのフィールドを検証してみましょう。

フィールドの定義も Maybe Address に変更する必要がある。validateAddress は以下のようにしたら動いた。

validateAddress :: Maybe Address -> V Errors (Maybe Address)
validateAddress addr = traverse (\a -> address <$> nonEmpty "Street"  a.street
                                               <*> nonEmpty "City"    a.city
                                               <*> lengthIs "State" 2 a.state) addr


この記事が気に入ったらサポートをしてみませんか?