実例によるPureScript 6 章
型クラスの章。型クラスとそのインスタンスの関係は、普通のオブジェクト志向言語のクラスとインスタンスが一個上にずれている感じ。
これは book に答えがあるが。
instance shapeShow :: Show Shape where
show shape = showShape shape
instance showComplex :: Show Complex where
show (Complex c) = show c.real <> " + " <> show c.imaginary <> "i"
instance eqComplex :: Eq Complex where
eq (Complex a) (Complex b) = a.real == b.real && a.imaginary == b.imaginary
instance nonEmptyEq :: (Eq a, Eq (Array a)) => Eq (NonEmpty a) where
eq (NonEmpty x1 xs1) (NonEmpty x2 xs2) = eq x1 x2 && eq xs1 xs2
instance nonEmptySemigroup :: Semigroup (Array a) => Semigroup (NonEmpty a) where
append (NonEmpty x1 xs1) (NonEmpty x2 xs2) = NonEmpty x1 (xs1 <> [x2] <> xs2)
instance nonEmptyFunctor :: Functor NonEmpty where
map f (NonEmpty x xs) = NonEmpty (f x) (map f xs)
Eq インスタンスも要るはず。
instance eqExtended :: (Eq a) => Eq (Extended a) where
eq Infinite Infinite = true
eq (Finite a) (Finite b) = eq a b
eq _ _ = false
instance ordExtended :: (Ord a) => Ord (Extended a) where
compare Infinite Infinite = EQ
compare Infinite (Finite _) = GT
compare (Finite _) Infinite = LT
compare (Finite a) (Finite b) = compare a b
instance nonEmptyFoldable :: Foldable NonEmpty where
foldr f init (NonEmpty x xs) = foldr f init ([x] <> xs)
foldl f init (NonEmpty x xs) = foldl f init ([x] <> xs)
foldMap f (NonEmpty x xs) = foldMap f ([x] <> xs)
これは NonEmpty をより一般化したものということかな。
instance foldableOneMore :: Foldable f => Foldable (OneMore f) where
foldr func init (OneMore x fx) = func x (foldr func init fx)
foldl func init (OneMore x fx) = func (foldl func init fx) x
foldMap func (OneMore x fx) = (func x) <> (foldMap func fx)
oneMore1 :: OneMore Array Int
oneMore1 = OneMore 1 [2, 3, 4, 5]
> foldl (-) 0 oneMore1
-15
> foldr (-) 0 oneMore1
3
> foldMap show oneMore1
"12345"
partialMax :: Partial => Array Int -> Int
partialMax xs =
case maximum xs of
Just a -> a
使ってみる。
> import Partial.Unsafe (unsafePartial)
> unsafePartial partialMax [1, 2, 3]
3
0 以下の繰り返しは "" を返すものとする。
instance repeatAction :: Action Multiply String where
act (Multiply n) s | n < 1 = ""
| otherwise = applyN ((<>) s) (n - 1) s
> act (Multiply 3) "hoge"
"hogehogehoge"
> act (Multiply 0) "hoge"
""
> act ((Multiply 2) <> (Multiply 3)) "hoge"
"hogehogehogehogehogehoge"
> act (Multiply 2) (act (Multiply 3) "hoge")
"hogehogehogehogehogehoge"
> act (Multiply 1) "hoge"
"hoge"
instance arrayAction :: Action m a => Action m (Array a) where
act m = map (act m)
> act (Multiply 3) ["hoge", "fuga", "foo"]
["hogehogehoge","fugafugafuga","foofoofoo"]
instance selfAction :: Monoid m => Action m (Self m) where
act a (Self b) = Self (b <> a)
instance showSelf :: Show a => Show (Self a) where
show (Self a) = "Self: " <> show a
> act (Multiply 3) (Self (Multiply 2))
Self: Multiply 6
多分関連づける必要はない、と思う。Stream の例のように stream と element が配列と要素の関係であるという制約はないはずなので。
hasDuplicate :: forall a. Hashable a => Array a -> Boolean
hasDuplicate xs = length xs > length removed
where
removed = nubByEq (\a b -> (hashEqual a b) && (a == b)) xs
> hasDuplicate [1, 2, 3, 2]
true
> hasDuplicate [1, 2, 3, 65536]
false
instance hashHour :: Hashable Hour where
hash (Hour n) = hash (mod n 12)
> import Data.Hashable (class Hashable, hashEqual, hash)
> hashEqual (Hour 1) (Hour 1)
true
> hashEqual (Hour 2) (Hour 14)
true
> hashEqual (Hour 2) (Hour 1)
false
以下のような実装になっている。各パターンで a, b が Hashable なので、a, b が同じ値なら hash 関数が返す値も同じになっている、と言える、ハズ。
instance hashMaybe :: Hashable a => Hashable (Maybe a) where
hash Nothing = hashCode 0
hash (Just a) = hashCode 1 `combineHashes` hash a
instance hashTuple :: (Hashable a, Hashable b) => Hashable (Tuple a b) where
hash (Tuple a b) = hash a `combineHashes` hash b
instance hashEither :: (Hashable a, Hashable b) => Hashable (Either a b) where
hash (Left a) = hashCode 0 `combineHashes` hash a
hash (Right b) = hashCode 1 `combineHashes` hash b
この記事が気に入ったらサポートをしてみませんか?