Andrew McMiddlin
20190515
typeclassextensions.lhs:3:3: error:
• Too many parameters for class ‘Foo’
(Enable MultiParamTypeClasses to allow multiparameter classes)
• In the class declaration for ‘Foo’

3  > class Foo a b where
 ^^^^^^^^^^^^^^^^^^^...
Haskell 2010 is defined in the Haskell 2010 Language Report.
[Char]
Section 12.3 covers the LANGUAGE
pragma, which is used for extensions.
{# LANGUAGE OverloadedStrings #}
{# LANGUAGE GADTs, ScopedTypeVariables #}
defaultextensions: OverloadedStrings
, GADTs
, ScopedTypeVariables
ghc XOverloadedStrings Foo.hs
$ ghci
λ :set XOverloadedStrings
OverloadedStrings
Enable overloaded string literals.
GHCi, version 8.6.4: http://www.haskell.org/ghc/ :? for help
Loaded GHCi configuration from /home/andrew/git/dotfiles/.ghci
λ> :t "Lambda"
"Lambda" :: [Char]
λ> :set XOverloadedStrings
λ> :t "Jam"
"Jam" :: Data.String.IsString p => p
class IsString a where
fromString :: String > a
instance IsString Text where
fromString = pack
isGood :: Text > Bool
isGood "foo"
TupleSections
Allow partially applied tuple constructors.
\x > x * 2
(* 2)
\x > (x,True)
(,True)
(,True,,,"hi",) :: a > b > c > d > (a,Bool,b,c,String,d)
InstanceSigs
Allow type signatures for definitions of instance members.
instance (Traversable f, Traversable g) => Traversable (Compose f g)
traverse :: (a > h b) > Compose f g a > h (Compose f g b)
traverse = undefined
• Illegal type signature in instance declaration:
traverse' :: (a > h b) > Compose f g a > h (Compose f g b)
(Use InstanceSigs to allow this)
• In the instance declaration for ‘Traversable' (Compose f g)’

25  traverse' :: (a > h b) > Compose f g a > h (Compose f g b)
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LambdaCase
Adds syntactic sugar for pattern matching on a function’s argument.
pretty ::
> Expr
> Text
pretty e = case e of
LitI n > pack $ show n
LitB True > "true"
LitB False > "false"
pretty ::
> Expr
> Text
pretty = \case
LitI n > pack $ show n
LitB True > "true"
LitB False > "false"
MultiWayIf
Adds syntactic sugar for nested ifthenelse
expressions.
if 1 < 0 then
"foo"
else if 12 > 4 then
"bar"
else if even 42 then
"42"
else
"no idea"
if  1 < 0 > "foo"
 12 > 4 > "bar"
 even 42 > "42"
 otherwise > "no idea"
RecordWildCards
Elide fields from record construction and pattern matching.
{# LANGUAGE RecordWildCards #}
data Person =
Person {
firstName :: Text
, surname :: Text
, height :: Integer
}
greetPerson ::
Person
> Text
greetPerson Person{firstName = firstName, surname = surname, height = height}Person{..} =
undefined
{# LANGUAGE RecordWildCards #}
defaultPerson ::
Person
defaultPerson =
let
firstName = "Andrew"
surname = "McMiddlin"
height = 185
in
Person {..}
{# LANGUAGE DuplicateRecordFields #}
{# LANGUAGE RecordWildCards #}
data ConferenceAttendee =
ConferenceAttendee {
firstName :: Text
, surname :: Text
, height :: Integer
, shirtSize :: ShirtSize
}
defaultConferenceAttendee ::
Person
> ConferenceAttendee
defaultConferenceAttendee Person{..} =
ConferenceAttendee {shirtSize = M, ..}
Some problems with RecordWildCards
NamedFieldPuns
Remove some of the boilerplate when bringing record fields into scope.
{# LANGUAGE NamedFieldPuns #}
greetPerson ::
Person
> Text
greetPerson Person{firstName, surname, height} =
undefined
{# LANGUAGE NamedFieldPuns #}
greetPerson ::
Person
> Text
greetPerson Person{firstName, surname} =
undefined
ScopedTypeVariables
Scope type variables to the lexical scope of the expression.
f ::
[a] > [a]
f xs =
ys ++ ys
where
ys :: [a]
ys = reverse xs
Couldn't match type ‘a’ with ‘a1’
‘a’ is a rigid type variable bound by
the type signature for:
f :: forall a. [a] > [a]
at examples/ScopedTypeVariables.hs:(5,1)(6,12)
‘a1’ is a rigid type variable bound by
the type signature for:
ys :: forall a1. [a1]
at examples/ScopedTypeVariables.hs:10:513
Expected type: [a1]
Actual type: [a]
{# LANGUAGE ScopedTypeVariables #}
f ::
forall a.
[a] > [a]
f xs =
ys ++ ys
where
ys :: [a]
ys = reverse xs
GeneralisedNewtypeDeriving
Derive instances for newtype
s based on the type they wrap.
class Pretty a where
pretty :: a > Text
instance Pretty Int where
pretty = pack . show
newtype Age = Age Int
deriving (Show, Pretty)
Can't make a derived instance of ‘Pretty Age’:
‘Pretty’ is not a stock derivable class (Eq, Show, etc.)
Try GeneralizedNewtypeDeriving for GHC's newtypederiving extension
class Coercible a b
coerce :: Coercible a b => a > b
{# LANGUAGE GeneralisedNewtypeDeriving #}
instance Pretty Int where
pretty = pack . show
newtype Age = Age Int
deriving (Show, Pretty)
instance Coercible Int Age
instance Coercible Age Int
instance Pretty Age where
pretty = coerce $ pack . show
instance Coercible a b => Coercible (a > c) (b > c)
GeneralisedNewtypeDeriving
as it was originally implemented had some issues that resulted in roles being added to the language.
As a result of the role system, adding join
to the Monad
class would stop GeneralisedNewtypeDeriving
from being able to derive Monad
.
Section 4.3.1 of the standard covers type classes.
To summarise, it says that a type class declaration must have the following form.
class cx => C u where cdecls
class
keyword;
class Show a where
show :: a > String
...
class Eq a => Ord a where
compare :: a > a > Ordering
...
class (Ord a, Show a) => ShOrd a
Section 4.3.2 of the standard covers type class instance declarations.
In short, it says that a type class instance must have the following form.
instance cx => C (T u1 … uk) where { d }
instance
keyword;
MultiParamTypeClasses
Allows type classes with more than one type parameter.
class Monad m => MonadReader r m where
ask :: m r
...
FlexibleInstances
Relaxes the rules for valid type class instances.
class Monad m => MonadReader r m where
ask :: m r
instance MonadReader r ((>) r) where
ask = id
typeclassextensions.lhs:123:1032: error:
• Illegal instance declaration for ‘MonadReader r ((>) r)’
(All instance types must be of the form (T a1 ... an)
where a1 ... an are *distinct type variables*,
and each type variable appears at most once in the instance head.
Use FlexibleInstances if you want to disable this.)
• In the instance declaration for ‘MonadReader r ((>) r)’

123  instance MonadReader r ((>) r) where
class Twizzle a where
twizzle :: a > Int
instance Twizzle (Maybe Integer) where
twizzle = maybe 42 fromInteger
$ ghc version
The Glorious Glasgow Haskell Compilation System, version 8.4.4
$ ghc Wall fforcerecomp Main.hs o whoopsie
[1 of 4] Compiling FIA ( FIA.hs, FIA.o )
[2 of 4] Compiling FIB ( FIB.hs, FIB.o )
[3 of 4] Compiling FIC ( FIC.hs, FIC.o )
[4 of 4] Compiling Main ( Main.hs, Main.o )
Linking whoopsie ...
> ./whoopsie
fromList [Whoopsie A1 B C,Whoopsie A2 B C,Whoopsie A1 B C]
FlexibleContexts
Relax some of the requirements regarding contexts.
updateThing ::
MonadState MyState m
=> m ()
updateThing ::
( HasThing s
, MonadState s m
)
=> m ()
FunctionalDependencies
Express dependent relationships between type variables for type classes with multiple parameters.
{# LANGUAGE FlexibleInstances #}
{# LANGUAGE MultiParamTypeClasses #}
class Monad m => MonadReader r m where
ask :: m r
instance MonadReader r ((>) r) where
ask = id
foo ::
Integer
foo =
(+ 1) <$> ask $ 41
typeclassextensions.lhs:275:1316: error:
• Ambiguous type variable ‘t0’ arising from a use of ‘ask’
prevents the constraint ‘(MonadReader
Integer ((>) t0))’ from being solved.
Probable fix: use a type annotation to specify what ‘t0’ should be.
These potential instance exist:
one instance involving outofscope types
(use fprintpotentialinstances to see them all)
• In the second argument of ‘(<$>)’, namely ‘ask’
In the expression: (+ 1) <$> ask
In the expression: (+ 1) <$> ask $ 100

275  (+ 1) <$> ask $ 41
 ^^^
{# LANGUAGE FlexibleInstances #}
{# LANGUAGE MultiParamTypeClasses #}
{# LANGUAGE FunctionalDependencies #}
class Monad m => MonadReader r m  m > r where
ask :: m r
instance MonadReader r ((>) r) where
ask = id
foo ::
Integer
foo =
(+ 1) <$> ask $ 41
GHC language extensions
https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html
Haskell 2010 report
https://www.haskell.org/onlinereport/haskell2010/haskellch12.html#x1919100012.3
24 Days of GHC extensions
https://ocharles.org.uk/pages/2014120124daysofghcextensions.html
Putting join
in Monad
https://ryanglscott.github.io/2018/03/04/howquantifiedconstraintscanletusputjoinbackinmonad/
FlexibleInstances
breaking Data.Set
https://gist.github.com/rwbarton/dd8e51dce2a262d17a80
Muhammad Ali
https://commons.wikimedia.org/wiki/File:Muhammad_Ali_1966.jpg
Records
https://flic.kr/p/8fsrnG