FP-Syd, May 2013


The May 2013 meeting of the FP-Syd functional programming group in Sydney heard talks about variance in Scala, monoids, and optimising pure loops. Posted by Thomas Sutton on May 29, 2013

Sounds like BayHAC was interesting.

Jed on variance (in Scala)

Variance is essentially about substitution or sub-typing. A thing that produces a Super may be replaced with a thing that takes Sub. A think that that takes Sub may be replaces by a thing that takes `Super.

Rat -> Real <: Int -> Complex

Reference to

Be liberal in what you accept and conservative in what you produce.

Use site variance in Java

final function Option<a>

In Scala:

List[+A]

Function[-T1, +R]

Kleisli[M[+_], -A, +B]

Eg:

class GPar
class Par extends GPar
class Child extends Par

class Box[+A]

def foo(x:Bor[Par]): 

foo(Box[Child])
foo(Box[GPar]) // error

f

trait Box[+A] {
	def get: A
	def take(a: A) // Error
}

trait Box[-A] {
	def get: A
	def take(a: A)
}

Functor

trait Functor[F[_]] {
	def map[A,B](a: F[A])(f: A => B): F[B]
}

This is actually a contra-variant functor.

trait Contravariant[F[_]] {
	def contramap[A,B](r: R[A])(f: B=>A): F[B]
}

Variance in mutable values:

Two type variables. One goes up (things coming out?), one goes down (things going in?).

http://biosimilarity.blogspot.com.au/2011/05/of-monads-and-games.html

Tim on monoid

class Monoid a where
    mempty :: a
    mappend :: a -> a -> a

Obeys laws

mappend a mempty == a
mappend mempty a == a
mappend a (mappend b c) == mappend (mappend a b) c

Given types may have multiple monoids: numbers have (+, 0) and (*, 1).

Define monoids to do min, max, count on the pattern of Sum and Product. Have a smart constructor for each

The foldable type-class makes fold polymorphic.

class Foldable t where
    foldMap :: Monoid m => (a -> m) -> t a -> m

Use the monoids we defined earlier:

foldMap sum as
foldMap count as
foldMap max as

The mappend operation distributes through structures like tuple types too. This lets apply multiple monoids with one traversal.

a2 :: Applicative a => a b -> a c -> a (b, c)
a2 b c = (,) <$> b <*> c

> foldMap (a2 min max) as
(Min 1, Max 456)

This doesn’t let us do Mean very nicely. We need to unpack the pair at the end and calculate the actual

Have an additional Aggregation class (superclass of Monoid) which has an associated type for the result which is extracted from the aggregation.

So we can make a version of foldMap which can finish and unwrap the aggregation:

afoldMap :: (Foldable t, Aggregation a) => (v -> a) -> t v -> AggResult a
afoldMap f vs = AggResult (foldMap f vs)

Combine the aggregation and monoid to apply a filter during the single traversal.

Two monoids for maps:

  1. Replace the values

  2. Insist the values are monoids too and append them.

Compose accessors with the “smart” constructors and apply them to calculate statistics over a stream of records.

Amos Robinson on optimising purely functional loops

Live at UNSW and looking at some optimisation problems. SpecConstr (constructor specialisation) is part of GHC (phase? optimisation?); has some problems, particularly with stream fusion, DPH, etc.

Dot product (pairwise multiple two vectors and sum the results) is a motivating example. We want to write that as:

dotp as bs = fold (+) 0 $ zipWith (*) as bs

But we want to actually execute:

dotp as bs = go 0 0
  where
    go i acc
    | i > V.length as
    = acc
    | otherwise
    = go (i+1) (acc + (as!i * bs!i))

(Assuming that the Ints aren’t boxed, etc.)

This post was published on May 29, 2013 and last modified on January 26, 2024. It is tagged with: event, fp-syd, meetup, functional programming, scala, haskell, variance, monoids.