SlideShare a Scribd company logo
Applicative Functors
Łukasz Marchewka @scalac
Functor
Functor
class Functor f where
fmap :: (a -> b) -> f a -> f b
Functor
class Functor f where
fmap :: (a -> b) -> f a -> f b
Functor
class Functor f where
fmap :: (a -> b) -> f a -> f b
Functor
class Functor f where
fmap :: (a -> b) -> f a -> f b
Functor
class Functor f where
fmap :: (a -> b) -> f a -> f b
Functor
class Functor f where
fmap :: (a -> b) -> f a -> f b
Monad
Monad
class Functor f where
fmap :: (a -> b) -> f a -> f b
class Applicative m => Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
Monad
class Functor f where
fmap :: (a -> b) -> f a -> f b
class Applicative m => Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
Monad
class Functor f where
fmap :: (a -> b) -> f a -> f b
class Applicative m => Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
Monad
class Functor f where
fmap :: (a -> b) -> f a -> f b
class Applicative m => Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
Monad
class Functor f where
fmap :: (a -> b) -> f a -> f b
class Applicative m => Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
Monad
class Functor f where
fmap :: (a -> b) -> f a -> f b
class Applicative m => Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
Monad
class Functor f where
fmap :: (a -> b) -> f a -> f b
class Applicative m => Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
Monad
class Functor f where
fmap :: (a -> b) -> f a -> f b
class Applicative m => Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
Monad
class Functor f where
fmap :: (a -> b) -> f a -> f b
class Applicative m => Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
Applicative
Applicative
class Functor f where
fmap :: (a -> b) -> f a -> f b
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
class Applicative m => Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
Applicative
class Functor f where
fmap :: (a -> b) -> f a -> f b
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
class Applicative m => Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
Applicative
class Functor f where
fmap :: (a -> b) -> f a -> f b
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
class Applicative m => Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
Applicative
class Functor f where
fmap :: (a -> b) -> f a -> f b
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
class Applicative m => Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
Applicative
class Functor f where
fmap :: (a -> b) -> f a -> f b
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
class Applicative m => Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
Applicative
class Functor f where
fmap :: (a -> b) -> f a -> f b
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
class Applicative m => Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
Applicative
class Functor f where
fmap :: (a -> b) -> f a -> f b
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
class Applicative m => Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
Applicative
class Functor f where
fmap :: (a -> b) -> f a -> f b
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
class Applicative m => Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
Applicative
class Functor f where
fmap :: (a -> b) -> f a -> f b
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
class Applicative m => Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
Applicative
class Functor f where
fmap :: (a -> b) -> f a -> f b
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
class Applicative m => Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
Applicative
class Functor f where
fmap :: (a -> b) -> f a -> f b
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
class Applicative m => Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
Applicative
class Functor f where
fmap :: (a -> b) -> f a -> f b
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
class Applicative m => Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
Applicative
class Functor f where
fmap :: (a -> b) -> f a -> f b
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
class Applicative m => Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
Applicative
class Functor f where
fmap :: (a -> b) -> f a -> f b
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
class Applicative m => Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
Details
Applicative
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
liftA2 :: (a -> b -> c) -> f a -> f b -> f c
(*>) :: f a -> f b -> f b
(<*) :: f a -> f b -> f a
Applicative
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
liftA2 :: (a -> b -> c) -> f a -> f b -> f c
(*>) :: f a -> f b -> f b
(<*) :: f a -> f b -> f a
Applicative
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
liftA2 :: (a -> b -> c) -> f a -> f b -> f c
(*>) :: f a -> f b -> f b
(<*) :: f a -> f b -> f a
Applicative
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
liftA2 :: (a -> b -> c) -> f a -> f b -> f c
(*>) :: f a -> f b -> f b
(<*) :: f a -> f b -> f a
Applicative
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
liftA2 :: (a -> b -> c) -> f a -> f b -> f c
(*>) :: f a -> f b -> f b
(<*) :: f a -> f b -> f a
Applicative
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
liftA2 :: (a -> b -> c) -> f a -> f b -> f c
(*>) :: f a -> f b -> f b
(<*) :: f a -> f b -> f a
Applicative
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
liftA2 :: (a -> b -> c) -> f a -> f b -> f c
(*>) :: f a -> f b -> f b
(<*) :: f a -> f b -> f a
Simple example
Types
newtype Nickname = Nickname { getNickname :: String }
newtype Age = Age { getAge :: Int }
data User = User Nickname Age
> :t User
User :: Nickname -> Age -> User
As a function
readNickname :: Nickname
readAge :: Age
readUser :: User
readUser = User readNickname readAge
With a context
readNickname' :: IO Nickname
readAge' :: IO Age
Using Monad
readNickname' :: IO Nickname
readAge' :: IO Age
readUserM :: IO User
readUserM = do
nickname <- readNickname'
age <- readAge'
return $ User nickname age
Using Applicative
readNickname' :: IO Nickname
readAge' :: IO Age
readUserA :: IO User
readUserA = pure User <*> readNickname' <*> readAge'
readNickname' :: IO Nickname
readAge' :: IO Age
readUserA :: IO User
readUserA = User <$> readNickname' <*> readAge'
Using Applicative
readNickname' :: IO Nickname
readAge' :: IO Age
readUserA :: IO User
readUserA = User <$> readNickname' <*> readAge'
Using Applicative
An infix synonym for 'fmap'
(<$>) :: Functor f => (a -> b) -> f a -> f b
(<$>) = fmap
Function vs Applicative
readNickname :: Nickname
readAge :: Age
User readNickname readAge
readNickname' :: IO Nickname
readAge' :: IO Age
User <$> readNickname' <*> readAge'
Applicative vs Monad
readNickname' :: IO Nickname
readNickname' = do
putStrLn "Your nickname:"
str <- getLine
if length str > 0
then return $ Nickname str
else error "Nickname can't be empty"
readAge' :: IO Age
readAge' = do
putStrLn "Your age:"
fmap (Age . read) getLine
Applicative vs Monad
readUserA :: IO User
readUserA = User <$> readNickname' <*> readAge'
readUserM :: IO User
readUserM = do
nickname <- readNickname'
age <- readAge'
return $ User nickname age
Applicative
Functor < Applicative < Monad
Why ?
Relation
Functor
Relation
Functor
Applicative
Relation
Functor
Applicative
Monad
When we need
● Context-free validation/parsing/transformation/optimization/...
● Parallel computation
● Traverlable
● Easier to compose than Monads
● When we can’t / don’t want to create Monad because of extra laws
Relation
Functor
Applicative
Monad
Examples
Example: Validation
● ???
● ???
● ...
Example: Validation
● Option
● Try
● Either
● ...
Example: Validation
data Either a b = Left a | Right b
Example: Validation
validateNickname :: String -> Either [String] Nickname
validateNickname str
| size < 1 = Left [ "Nickname must have at least 1 character" ]
| size > 10 = Left [ "Nickname must have at most 10 characters" ]
| otherwise = Right $ Nickname str
where size = Data.List.length str
validateAge :: Int -> Either [String] Age
validateAge val
| val < 0 = Left [ "Minimal age is 0" ]
| val > 150 = Left [ "Maximal age is 150" ]
| otherwise = Right $ Age val
Example: Validation
validateUser :: String -> Int -> Either [String] User
validateUser nickname age =
User
<$> (validateNickname nickname)
<*> (validateAge age)
Example: Validation
> validateUser "" 200
Example: Validation
> validateUser "" 200
Left ["Nickname must have at least 1 character"]
Example: Validation
> validateUser "" 200
Left ["Nickname must have at least 1 character"]
> validateUser "john" 200
Example: Validation
> validateUser "" 200
Left ["Nickname must have at least 1 character"]
> validateUser "john" 200
Left ["Maximal age is 150"]
Example: Validation
> validateUser "" 200
Left ["Nickname must have at least 1 character"]
> validateUser "john" 200
Left ["Maximal age is 150"]
> validateUser "john" 20
Right (User (Nickname {getNickname = "john"}) (Age {getAge = 20}))
Example: Validation
data Either a b = Left a | Right b
Example: Validation
data Either a b = Left a | Right b -- fail fast
Example: Validation
import Data.Validation
data Validation err a = Failure err | Success a
data Either a b = Left a | Right b
Example: Validation
● A data-type like Either but with an accumulating Applicative
● The Validation data type is isomorphic to Either
● An applicative functor that is not a monad
Example: Validation
● A data-type like Either but with an accumulating Applicative
● The Validation data type is isomorphic to Either
● An applicative functor that is not a monad
Example: Validation
validateNicknameA :: String -> Validation (NonEmpty String) Nickname
validateNicknameA str
| size < 1 = Failure $ "Nickname must have at least 1 character" :| []
| size > 10 = Failure $ "Nickname must have at most 10 characters" :| []
| otherwise = Success $ Nickname str
where size = Data.List.length str
validateAgeA :: Int -> Validation (NonEmpty String) Age
validateAgeA val
| val < 0 = Failure $ "Minimal age is 0" :| []
| val > 150 = Failure $ "Maximal age is 150" :| []
| otherwise = Success $ Age val
Example: Validation
validateUserA :: String -> Int -> Validation (NonEmpty String) User
validateUserA nickname age =
User
<$> (validateNicknameA nickname)
<*> (validateAgeA age)
Example: Validation
> validateUserA "" 200
Example: Validation
> validateUserA "" 200
Failure ("Nickname must have at least 1 character" :| ["Maximal age is 150"])
Example: Validation
> validateUserA "" 200
Failure ("Nickname must have at least 1 character" :| ["Maximal age is 150"])
> validateUserA "john" 20
Success (User (Nickname {getNickname = "john"}) (Age {getAge = 20}))
Either vs Validation
instance Applicative (Either e) where
pure = Right
Left e <*> _ = Left e
Right f <*> r = fmap f r
instance Applicative (Validation err) where
pure = Success
Failure e1 <*> b = Failure $ case b of
Failure e2 -> e1 <> e2
Success _ -> e1
Success _ <*> Failure e2 =
Failure e2
Success f <*> Success a =
Success (f a)
Example: haxl
● batch multiple requests to the same data source
● request data from multiple data sources concurrently
● cache previous requests
● memoize computations
numCommonFriends x y =
length
<$> (intersect <$> friendsOf x <*> friendsOf y)
Example: Composition
readValidNickname :: IO (Maybe Nickname)
readValidNickname = do
putStrLn "Your name:"
str <- getLine
if length str > 0
then return $ Just $ Nickname str
else return Nothing
readValidAge :: IO (Maybe Age)
readValidAge = do
putStrLn "Your age:"
str <- getLine
return $ fmap Age $ readMaybe str
Example: Composition
readValidUserM :: IO (Maybe User)
readValidUserM = runMaybeT $ do
nickname <- MaybeT readValidNickname
age <- MaybeT readValidAge
return $ User nickname age
Example: Composition
readValidUserA :: IO (Maybe User)
readValidUserA = unComp1
(User <$> (Comp1 readValidNickname) <*> (Comp1 readValidAge))
Example: Composition
readValidUserA :: IO (Maybe User)
readValidUserA = unComp1
(User <$> (Comp1 readValidNickname) <*> (Comp1 readValidAge))
newtype (:.:) (f :: k2 -> Type) (g :: k1 -> k2) (p :: k1) =
Comp1 { unComp1 :: f (g p) }
Example: Composition
newtype (:.:) (f :: k2 -> Type) (g :: k1 -> k2) (p :: k1) =
Comp1 { unComp1 :: f (g p) }
instance (Applicative f, Applicative g) => Applicative (f :.: g) where
pure x = Comp1 (pure (pure x))
Comp1 f <*> Comp1 x = Comp1 (liftA2 (<*>) f x)
liftA2 f (Comp1 x) (Comp1 y) = Comp1 (liftA2 (liftA2 f) x y)
Example: Free
data Field a =
StringField Name Doc
| IntField Name Doc
| BoolField Name Doc
| ObjectField Name Doc (Ap Field a)
Example: Free
type Dsl a = Ap Field a
string :: Name -> Doc -> Dsl String
string n d = liftAp $ StringField n d
int :: Name -> Doc -> Dsl Int
int n d = liftAp $ IntField n d
bool :: Name -> Doc -> Dsl Bool
bool n d = liftAp $ BoolField n d
object :: Name -> Doc -> Dsl a -> Dsl a
object n d a = liftAp $ ObjectField n d a
Example: Free
data User = User String Int Bool
data Comment = Comment String User
user :: Dsl User
user = User
<$> string "name" "user's name"
<*> int "age" "user's age"
<*> bool "active" "is active"
comment :: Dsl Comment
comment = Comment
<$> string "title" "short desc"
<*> object "creator" "who created the comment" user
Example: Free
Comment
User String
String Int Bool
Example: Free
genDoc :: Int -> Field a -> [String]
genDoc indent (StringField n d) = [printf "%*s- %s : string - %s" indent "" n d]
genDoc indent (IntField n d) = [printf "%*s- %s : int - %s" indent "" n d]
genDoc indent (BoolField n d) = [printf "%*s- %s : bool - %s" indent "" n d]
genDoc indent (ObjectField n d m) = asString : nested
where
asString = printf "%*s- %s : obj - %s" indent "" n d
nested = runAp_ (genDoc $ indent + 2) m
Example: Free
printDoc :: IO ()
printDoc = mapM_ putStrLn lines
where lines = runAp_ (genDoc 0) comment
- title : string - short desc
- creator : obj - creator of the comment
- name : string - user's name
- age : int - user's age
- active : bool - is active
Example: Free
● JSON, XML, ... <-> Model
● Transformation (context-free)
● … (context-free)
Thank You!
lukasz.marchewka@gmail.com
https://github.com/LukaszMarchewka/haskell-applicative-demo

More Related Content

Similar to Applicative functors by Łukasz Marchewka (8)

アプリカティブファンクターとHaskell 2014版
アプリカティブファンクターとHaskell 2014版アプリカティブファンクターとHaskell 2014版
アプリカティブファンクターとHaskell 2014版
 
09. haskell Context
09. haskell Context09. haskell Context
09. haskell Context
 
10. haskell Modules
10. haskell Modules10. haskell Modules
10. haskell Modules
 
Functions in python
Functions in pythonFunctions in python
Functions in python
 
Swift 3.0 で変わったところ - 厳選 13 項目 #love_swift #cswift
Swift 3.0 で変わったところ - 厳選 13 項目 #love_swift #cswiftSwift 3.0 で変わったところ - 厳選 13 項目 #love_swift #cswift
Swift 3.0 で変わったところ - 厳選 13 項目 #love_swift #cswift
 
Introduction to Monads in Scala (2)
Introduction to Monads in Scala (2)Introduction to Monads in Scala (2)
Introduction to Monads in Scala (2)
 
MP in Clojure
MP in ClojureMP in Clojure
MP in Clojure
 
하스켈 프로그래밍 입문 3
하스켈 프로그래밍 입문 3하스켈 프로그래밍 입문 3
하스켈 프로그래밍 입문 3
 

More from Scalac

Scala and Lift presentation
Scala and Lift presentationScala and Lift presentation
Scala and Lift presentation
Scalac
 

More from Scalac (16)

AWS Api Gateway by Łukasz Marchewka Scalacc
AWS Api Gateway by Łukasz Marchewka ScalaccAWS Api Gateway by Łukasz Marchewka Scalacc
AWS Api Gateway by Łukasz Marchewka Scalacc
 
Do ECTL not ETL: the art and science of data cleansing in data pipelines by P...
Do ECTL not ETL: the art and science of data cleansing in data pipelines by P...Do ECTL not ETL: the art and science of data cleansing in data pipelines by P...
Do ECTL not ETL: the art and science of data cleansing in data pipelines by P...
 
React Hooks by Oleksandr Oleksiv Scalac
React Hooks by Oleksandr Oleksiv ScalacReact Hooks by Oleksandr Oleksiv Scalac
React Hooks by Oleksandr Oleksiv Scalac
 
Introduction to Scala by Piotr Wiśniowski Scalac
Introduction to Scala by Piotr Wiśniowski ScalacIntroduction to Scala by Piotr Wiśniowski Scalac
Introduction to Scala by Piotr Wiśniowski Scalac
 
ZIO actors by Mateusz Sokół Scalac
ZIO actors by Mateusz Sokół ScalacZIO actors by Mateusz Sokół Scalac
ZIO actors by Mateusz Sokół Scalac
 
Why functional programming and category theory strongly matters - Piotr Parad...
Why functional programming and category theory strongly matters - Piotr Parad...Why functional programming and category theory strongly matters - Piotr Parad...
Why functional programming and category theory strongly matters - Piotr Parad...
 
Big picture of category theory in scala with deep dive into contravariant and...
Big picture of category theory in scala with deep dive into contravariant and...Big picture of category theory in scala with deep dive into contravariant and...
Big picture of category theory in scala with deep dive into contravariant and...
 
How to write automated tests and don’t lose your mind by Dorian Sarnowski Scalac
How to write automated tests and don’t lose your mind by Dorian Sarnowski ScalacHow to write automated tests and don’t lose your mind by Dorian Sarnowski Scalac
How to write automated tests and don’t lose your mind by Dorian Sarnowski Scalac
 
Do you have that Spark in your ECTL? by Piotr Sych Scalac
Do you have that Spark in your ECTL? by Piotr Sych ScalacDo you have that Spark in your ECTL? by Piotr Sych Scalac
Do you have that Spark in your ECTL? by Piotr Sych Scalac
 
Can we automate the process of backlog prioritizing? by Adam Gadomski Scalac
Can we automate the process of backlog prioritizing? by Adam Gadomski ScalacCan we automate the process of backlog prioritizing? by Adam Gadomski Scalac
Can we automate the process of backlog prioritizing? by Adam Gadomski Scalac
 
How to create the right sales funnel for your business? by Maciej Greń
How to create the right sales funnel for your business? by Maciej GreńHow to create the right sales funnel for your business? by Maciej Greń
How to create the right sales funnel for your business? by Maciej Greń
 
ActorRef[Typed] by Andrzej Kopeć
ActorRef[Typed] by Andrzej KopećActorRef[Typed] by Andrzej Kopeć
ActorRef[Typed] by Andrzej Kopeć
 
Scala 3camp 2011
Scala   3camp 2011Scala   3camp 2011
Scala 3camp 2011
 
Liftweb
LiftwebLiftweb
Liftweb
 
Scala == Effective Java
Scala == Effective JavaScala == Effective Java
Scala == Effective Java
 
Scala and Lift presentation
Scala and Lift presentationScala and Lift presentation
Scala and Lift presentation
 

Recently uploaded

Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology SolutionsProsigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns
 

Recently uploaded (20)

Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024
 
Understanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSageUnderstanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSage
 
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
 
Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.ILBeyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
 
How Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptxHow Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptx
 
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
 
First Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User EndpointsFirst Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User Endpoints
 
GraphAware - Transforming policing with graph-based intelligence analysis
GraphAware - Transforming policing with graph-based intelligence analysisGraphAware - Transforming policing with graph-based intelligence analysis
GraphAware - Transforming policing with graph-based intelligence analysis
 
2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx
 
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERRORTROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
 
Cyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdfCyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdf
 
Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024
 
Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology SolutionsProsigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology Solutions
 
AI/ML Infra Meetup | ML explainability in Michelangelo
AI/ML Infra Meetup | ML explainability in MichelangeloAI/ML Infra Meetup | ML explainability in Michelangelo
AI/ML Infra Meetup | ML explainability in Michelangelo
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
 
SOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBrokerSOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBroker
 
Agnieszka Andrzejewska - BIM School Course in Kraków
Agnieszka Andrzejewska - BIM School Course in KrakówAgnieszka Andrzejewska - BIM School Course in Kraków
Agnieszka Andrzejewska - BIM School Course in Kraków
 
How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?
How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?
How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?
 
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdfDominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
 
Studiovity film pre-production and screenwriting software
Studiovity film pre-production and screenwriting softwareStudiovity film pre-production and screenwriting software
Studiovity film pre-production and screenwriting software
 

Applicative functors by Łukasz Marchewka

  • 3. Functor class Functor f where fmap :: (a -> b) -> f a -> f b
  • 4. Functor class Functor f where fmap :: (a -> b) -> f a -> f b
  • 5. Functor class Functor f where fmap :: (a -> b) -> f a -> f b
  • 6. Functor class Functor f where fmap :: (a -> b) -> f a -> f b
  • 7. Functor class Functor f where fmap :: (a -> b) -> f a -> f b
  • 8. Functor class Functor f where fmap :: (a -> b) -> f a -> f b
  • 10. Monad class Functor f where fmap :: (a -> b) -> f a -> f b class Applicative m => Monad m where return :: a -> m a (>>=) :: m a -> (a -> m b) -> m b
  • 11. Monad class Functor f where fmap :: (a -> b) -> f a -> f b class Applicative m => Monad m where return :: a -> m a (>>=) :: m a -> (a -> m b) -> m b
  • 12. Monad class Functor f where fmap :: (a -> b) -> f a -> f b class Applicative m => Monad m where return :: a -> m a (>>=) :: m a -> (a -> m b) -> m b
  • 13. Monad class Functor f where fmap :: (a -> b) -> f a -> f b class Applicative m => Monad m where return :: a -> m a (>>=) :: m a -> (a -> m b) -> m b
  • 14. Monad class Functor f where fmap :: (a -> b) -> f a -> f b class Applicative m => Monad m where return :: a -> m a (>>=) :: m a -> (a -> m b) -> m b
  • 15. Monad class Functor f where fmap :: (a -> b) -> f a -> f b class Applicative m => Monad m where return :: a -> m a (>>=) :: m a -> (a -> m b) -> m b
  • 16. Monad class Functor f where fmap :: (a -> b) -> f a -> f b class Applicative m => Monad m where return :: a -> m a (>>=) :: m a -> (a -> m b) -> m b
  • 17. Monad class Functor f where fmap :: (a -> b) -> f a -> f b class Applicative m => Monad m where return :: a -> m a (>>=) :: m a -> (a -> m b) -> m b
  • 18. Monad class Functor f where fmap :: (a -> b) -> f a -> f b class Applicative m => Monad m where return :: a -> m a (>>=) :: m a -> (a -> m b) -> m b
  • 20. Applicative class Functor f where fmap :: (a -> b) -> f a -> f b class Functor f => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b class Applicative m => Monad m where return :: a -> m a (>>=) :: m a -> (a -> m b) -> m b
  • 21. Applicative class Functor f where fmap :: (a -> b) -> f a -> f b class Functor f => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b class Applicative m => Monad m where return :: a -> m a (>>=) :: m a -> (a -> m b) -> m b
  • 22. Applicative class Functor f where fmap :: (a -> b) -> f a -> f b class Functor f => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b class Applicative m => Monad m where return :: a -> m a (>>=) :: m a -> (a -> m b) -> m b
  • 23. Applicative class Functor f where fmap :: (a -> b) -> f a -> f b class Functor f => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b class Applicative m => Monad m where return :: a -> m a (>>=) :: m a -> (a -> m b) -> m b
  • 24. Applicative class Functor f where fmap :: (a -> b) -> f a -> f b class Functor f => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b class Applicative m => Monad m where return :: a -> m a (>>=) :: m a -> (a -> m b) -> m b
  • 25. Applicative class Functor f where fmap :: (a -> b) -> f a -> f b class Functor f => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b class Applicative m => Monad m where return :: a -> m a (>>=) :: m a -> (a -> m b) -> m b
  • 26. Applicative class Functor f where fmap :: (a -> b) -> f a -> f b class Functor f => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b class Applicative m => Monad m where return :: a -> m a (>>=) :: m a -> (a -> m b) -> m b
  • 27. Applicative class Functor f where fmap :: (a -> b) -> f a -> f b class Functor f => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b class Applicative m => Monad m where return :: a -> m a (>>=) :: m a -> (a -> m b) -> m b
  • 28. Applicative class Functor f where fmap :: (a -> b) -> f a -> f b class Functor f => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b class Applicative m => Monad m where return :: a -> m a (>>=) :: m a -> (a -> m b) -> m b
  • 29. Applicative class Functor f where fmap :: (a -> b) -> f a -> f b class Functor f => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b class Applicative m => Monad m where return :: a -> m a (>>=) :: m a -> (a -> m b) -> m b
  • 30. Applicative class Functor f where fmap :: (a -> b) -> f a -> f b class Functor f => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b class Applicative m => Monad m where return :: a -> m a (>>=) :: m a -> (a -> m b) -> m b
  • 31. Applicative class Functor f where fmap :: (a -> b) -> f a -> f b class Functor f => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b class Applicative m => Monad m where return :: a -> m a (>>=) :: m a -> (a -> m b) -> m b
  • 32. Applicative class Functor f where fmap :: (a -> b) -> f a -> f b class Functor f => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b class Applicative m => Monad m where return :: a -> m a (>>=) :: m a -> (a -> m b) -> m b
  • 33. Applicative class Functor f where fmap :: (a -> b) -> f a -> f b class Functor f => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b class Applicative m => Monad m where return :: a -> m a (>>=) :: m a -> (a -> m b) -> m b
  • 35. Applicative class Functor f => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b liftA2 :: (a -> b -> c) -> f a -> f b -> f c (*>) :: f a -> f b -> f b (<*) :: f a -> f b -> f a
  • 36. Applicative class Functor f => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b liftA2 :: (a -> b -> c) -> f a -> f b -> f c (*>) :: f a -> f b -> f b (<*) :: f a -> f b -> f a
  • 37. Applicative class Functor f => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b liftA2 :: (a -> b -> c) -> f a -> f b -> f c (*>) :: f a -> f b -> f b (<*) :: f a -> f b -> f a
  • 38. Applicative class Functor f => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b liftA2 :: (a -> b -> c) -> f a -> f b -> f c (*>) :: f a -> f b -> f b (<*) :: f a -> f b -> f a
  • 39. Applicative class Functor f => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b liftA2 :: (a -> b -> c) -> f a -> f b -> f c (*>) :: f a -> f b -> f b (<*) :: f a -> f b -> f a
  • 40. Applicative class Functor f => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b liftA2 :: (a -> b -> c) -> f a -> f b -> f c (*>) :: f a -> f b -> f b (<*) :: f a -> f b -> f a
  • 41. Applicative class Functor f => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b liftA2 :: (a -> b -> c) -> f a -> f b -> f c (*>) :: f a -> f b -> f b (<*) :: f a -> f b -> f a
  • 43. Types newtype Nickname = Nickname { getNickname :: String } newtype Age = Age { getAge :: Int } data User = User Nickname Age > :t User User :: Nickname -> Age -> User
  • 44. As a function readNickname :: Nickname readAge :: Age readUser :: User readUser = User readNickname readAge
  • 45. With a context readNickname' :: IO Nickname readAge' :: IO Age
  • 46. Using Monad readNickname' :: IO Nickname readAge' :: IO Age readUserM :: IO User readUserM = do nickname <- readNickname' age <- readAge' return $ User nickname age
  • 47. Using Applicative readNickname' :: IO Nickname readAge' :: IO Age readUserA :: IO User readUserA = pure User <*> readNickname' <*> readAge'
  • 48. readNickname' :: IO Nickname readAge' :: IO Age readUserA :: IO User readUserA = User <$> readNickname' <*> readAge' Using Applicative
  • 49. readNickname' :: IO Nickname readAge' :: IO Age readUserA :: IO User readUserA = User <$> readNickname' <*> readAge' Using Applicative
  • 50. An infix synonym for 'fmap' (<$>) :: Functor f => (a -> b) -> f a -> f b (<$>) = fmap
  • 51. Function vs Applicative readNickname :: Nickname readAge :: Age User readNickname readAge readNickname' :: IO Nickname readAge' :: IO Age User <$> readNickname' <*> readAge'
  • 52. Applicative vs Monad readNickname' :: IO Nickname readNickname' = do putStrLn "Your nickname:" str <- getLine if length str > 0 then return $ Nickname str else error "Nickname can't be empty" readAge' :: IO Age readAge' = do putStrLn "Your age:" fmap (Age . read) getLine
  • 53. Applicative vs Monad readUserA :: IO User readUserA = User <$> readNickname' <*> readAge' readUserM :: IO User readUserM = do nickname <- readNickname' age <- readAge' return $ User nickname age
  • 55. Why ?
  • 59. When we need ● Context-free validation/parsing/transformation/optimization/... ● Parallel computation ● Traverlable ● Easier to compose than Monads ● When we can’t / don’t want to create Monad because of extra laws
  • 63. Example: Validation ● Option ● Try ● Either ● ...
  • 64. Example: Validation data Either a b = Left a | Right b
  • 65. Example: Validation validateNickname :: String -> Either [String] Nickname validateNickname str | size < 1 = Left [ "Nickname must have at least 1 character" ] | size > 10 = Left [ "Nickname must have at most 10 characters" ] | otherwise = Right $ Nickname str where size = Data.List.length str validateAge :: Int -> Either [String] Age validateAge val | val < 0 = Left [ "Minimal age is 0" ] | val > 150 = Left [ "Maximal age is 150" ] | otherwise = Right $ Age val
  • 66. Example: Validation validateUser :: String -> Int -> Either [String] User validateUser nickname age = User <$> (validateNickname nickname) <*> (validateAge age)
  • 68. Example: Validation > validateUser "" 200 Left ["Nickname must have at least 1 character"]
  • 69. Example: Validation > validateUser "" 200 Left ["Nickname must have at least 1 character"] > validateUser "john" 200
  • 70. Example: Validation > validateUser "" 200 Left ["Nickname must have at least 1 character"] > validateUser "john" 200 Left ["Maximal age is 150"]
  • 71. Example: Validation > validateUser "" 200 Left ["Nickname must have at least 1 character"] > validateUser "john" 200 Left ["Maximal age is 150"] > validateUser "john" 20 Right (User (Nickname {getNickname = "john"}) (Age {getAge = 20}))
  • 72. Example: Validation data Either a b = Left a | Right b
  • 73. Example: Validation data Either a b = Left a | Right b -- fail fast
  • 74. Example: Validation import Data.Validation data Validation err a = Failure err | Success a data Either a b = Left a | Right b
  • 75. Example: Validation ● A data-type like Either but with an accumulating Applicative ● The Validation data type is isomorphic to Either ● An applicative functor that is not a monad
  • 76. Example: Validation ● A data-type like Either but with an accumulating Applicative ● The Validation data type is isomorphic to Either ● An applicative functor that is not a monad
  • 77. Example: Validation validateNicknameA :: String -> Validation (NonEmpty String) Nickname validateNicknameA str | size < 1 = Failure $ "Nickname must have at least 1 character" :| [] | size > 10 = Failure $ "Nickname must have at most 10 characters" :| [] | otherwise = Success $ Nickname str where size = Data.List.length str validateAgeA :: Int -> Validation (NonEmpty String) Age validateAgeA val | val < 0 = Failure $ "Minimal age is 0" :| [] | val > 150 = Failure $ "Maximal age is 150" :| [] | otherwise = Success $ Age val
  • 78. Example: Validation validateUserA :: String -> Int -> Validation (NonEmpty String) User validateUserA nickname age = User <$> (validateNicknameA nickname) <*> (validateAgeA age)
  • 80. Example: Validation > validateUserA "" 200 Failure ("Nickname must have at least 1 character" :| ["Maximal age is 150"])
  • 81. Example: Validation > validateUserA "" 200 Failure ("Nickname must have at least 1 character" :| ["Maximal age is 150"]) > validateUserA "john" 20 Success (User (Nickname {getNickname = "john"}) (Age {getAge = 20}))
  • 82. Either vs Validation instance Applicative (Either e) where pure = Right Left e <*> _ = Left e Right f <*> r = fmap f r instance Applicative (Validation err) where pure = Success Failure e1 <*> b = Failure $ case b of Failure e2 -> e1 <> e2 Success _ -> e1 Success _ <*> Failure e2 = Failure e2 Success f <*> Success a = Success (f a)
  • 83. Example: haxl ● batch multiple requests to the same data source ● request data from multiple data sources concurrently ● cache previous requests ● memoize computations numCommonFriends x y = length <$> (intersect <$> friendsOf x <*> friendsOf y)
  • 84. Example: Composition readValidNickname :: IO (Maybe Nickname) readValidNickname = do putStrLn "Your name:" str <- getLine if length str > 0 then return $ Just $ Nickname str else return Nothing readValidAge :: IO (Maybe Age) readValidAge = do putStrLn "Your age:" str <- getLine return $ fmap Age $ readMaybe str
  • 85. Example: Composition readValidUserM :: IO (Maybe User) readValidUserM = runMaybeT $ do nickname <- MaybeT readValidNickname age <- MaybeT readValidAge return $ User nickname age
  • 86. Example: Composition readValidUserA :: IO (Maybe User) readValidUserA = unComp1 (User <$> (Comp1 readValidNickname) <*> (Comp1 readValidAge))
  • 87. Example: Composition readValidUserA :: IO (Maybe User) readValidUserA = unComp1 (User <$> (Comp1 readValidNickname) <*> (Comp1 readValidAge)) newtype (:.:) (f :: k2 -> Type) (g :: k1 -> k2) (p :: k1) = Comp1 { unComp1 :: f (g p) }
  • 88. Example: Composition newtype (:.:) (f :: k2 -> Type) (g :: k1 -> k2) (p :: k1) = Comp1 { unComp1 :: f (g p) } instance (Applicative f, Applicative g) => Applicative (f :.: g) where pure x = Comp1 (pure (pure x)) Comp1 f <*> Comp1 x = Comp1 (liftA2 (<*>) f x) liftA2 f (Comp1 x) (Comp1 y) = Comp1 (liftA2 (liftA2 f) x y)
  • 89. Example: Free data Field a = StringField Name Doc | IntField Name Doc | BoolField Name Doc | ObjectField Name Doc (Ap Field a)
  • 90. Example: Free type Dsl a = Ap Field a string :: Name -> Doc -> Dsl String string n d = liftAp $ StringField n d int :: Name -> Doc -> Dsl Int int n d = liftAp $ IntField n d bool :: Name -> Doc -> Dsl Bool bool n d = liftAp $ BoolField n d object :: Name -> Doc -> Dsl a -> Dsl a object n d a = liftAp $ ObjectField n d a
  • 91. Example: Free data User = User String Int Bool data Comment = Comment String User user :: Dsl User user = User <$> string "name" "user's name" <*> int "age" "user's age" <*> bool "active" "is active" comment :: Dsl Comment comment = Comment <$> string "title" "short desc" <*> object "creator" "who created the comment" user
  • 93. Example: Free genDoc :: Int -> Field a -> [String] genDoc indent (StringField n d) = [printf "%*s- %s : string - %s" indent "" n d] genDoc indent (IntField n d) = [printf "%*s- %s : int - %s" indent "" n d] genDoc indent (BoolField n d) = [printf "%*s- %s : bool - %s" indent "" n d] genDoc indent (ObjectField n d m) = asString : nested where asString = printf "%*s- %s : obj - %s" indent "" n d nested = runAp_ (genDoc $ indent + 2) m
  • 94. Example: Free printDoc :: IO () printDoc = mapM_ putStrLn lines where lines = runAp_ (genDoc 0) comment - title : string - short desc - creator : obj - creator of the comment - name : string - user's name - age : int - user's age - active : bool - is active
  • 95. Example: Free ● JSON, XML, ... <-> Model ● Transformation (context-free) ● … (context-free)