I am trying to come up with an implementation of State Monad derived from examples of function composition. Here I what I came up with:
First deriving the concept of Monad:
data Maybe' a = Nothing' | Just' a deriving Show
sqrt' :: (Floating a, Ord a) => a -> Maybe' a
sqrt' x = if x < 0 then Nothing' else Just' (sqrt x)
inv' :: (Floating a, Ord a) => a -> Maybe' a
inv' x = if x == 0 then Nothing' else Just' (1/x)
log' :: (Floating a, Ord a) => a -> Maybe' a
log' x = if x == 0 then Nothing' else Just' (log x)
We can have function that composes these functions as follows:
sqrtInvLog' :: (Floating a, Ord a) => a -> Maybe' a
sqrtInvLog' x = case (sqrt' x) of
Nothing' -> Nothing'
(Just' y) -> case (inv' y) of
Nothing' -> Nothing'
(Just' z) -> log' z
This could be simplified by factoring out the case statement and function application:
fMaybe' :: (Maybe' a) -> (a -> Maybe' b) -> Maybe' b
fMaybe' Nothing' _ = Nothing'
fMaybe' (Just' x) f = f x
-- Applying fMaybe' =>
sqrtInvLog'' :: (Floating a, Ord a) => a -> Maybe' a
sqrtInvLog'' x = (sqrt' x) `fMaybe'` (inv') `fMaybe'` (log')`
Now we can generalize the concept to any type, instead of just Maybe' by defining a Monad =>
class Monad' m where
bind' :: m a -> (a -> m b) -> m b
return' :: a -> m a
instance Monad' Maybe' where
bind' Nothing' _ = Nothing'
bind' (Just' x) f = f x
return' x = Just' x
Using Monad' implementation, sqrtInvLog'' can be written as:
sqrtInvLog''' :: (Floating a, Ord a) => a -> Maybe' a
sqrtInvLog''' x = (sqrt' x) \bind'` (inv') `bind'` (log')`
Trying to apply the concept to maintain state, I defined something as shown below:
data St a s = St (a,s) deriving Show
sqrtLogInvSt' :: (Floating a, Ord a) => St a a -> St (Maybe' a) a
sqrtLogInvSt' (St (x,s)) = case (sqrt' x) of
Nothing' -> St (Nothing', s)
(Just' y) -> case (log' y) of
Nothing' -> St (Nothing', s+y)
(Just' z) -> St (inv' z, s+y+z)
It is not possible to define a monad using the above definition as bind needs to be defined as taking in a single type "m a".
Second attempt based on Haskell's definition of State Monad:
newtype State s a = State { runState :: s -> (a, s) }
First attempt to define function that is built using composed functions and maintains state:
fex1 :: Int->State Int Int
fex1 x = State { runState = \s->(r,(s+r)) } where r = x `mod` 2`
fex2 :: Int->State Int Int
fex2 x = State { runState = \s-> (r,s+r)} where r = x * 5
A composed function:
fex3 x = (runState (fex2 y)) st where (st, y) = (runState (fex1 x)) 0
But the definition newtype State s a = State { runState :: s -> (a, s) } does not fit the pattern of m a -> (a -> m b) -> m b of bind
An attempt could be made as follows:
instance Monad' (State s) where
bind' st f = undefined
return' x = State { runState = \s -> (x,s) }
bind' is undefined above becuase I did not know how I would implement it.
I could derive why monads are useful and apply it the first example (Maybe') but cannot seem to apply it to State. It will be useful to understand how I could derive the State Moand using concepts defined above.
Note that I have asked a similar question earlier: Haskell - Unable to define a State monad like function using a Monad like definition but I have expanded here and added more details.
Your composed function fex3 has the wrong type:
fex3 :: Int -> (Int, Int)
Unlike with your sqrtInvLog' example for Maybe', State does not appear in the type of fex3.
We could define it as
fex3 :: Int -> State Int Int
fex3 x = State { runState = \s ->
let (y, st) = runState (fex1 x) s in
runState (fex2 y) st }
The main difference to your definition is that instead of hardcoding 0 as the initial state, we pass on our own state s.
What if (like in your Maybe example) we wanted to compose three functions? Here I'll just reuse fex2 instead of introducing another intermediate function:
fex4 :: Int -> State Int Int
fex4 x = State { runState = \s ->
let (y, st) = runState (fex1 x) s in
let (z, st') = runState (fex2 y) st in
runState (fex2 z) st' }
SPOILERS:
The generalized version bindState can be extracted as follows:
bindState m f = State { runState = \s ->
let (x, st) = runState m s in
runState (f x) st }
fex3' x = fex1 x `bindState` fex2
fex4' x = fex1 x `bindState` fex2 `bindState` fex2
We can also start with Monad' and types.
The m in the definition of Monad' is applied to one type argument (m a, m b). We can't set m = State because State requires two arguments. On the other hand, partial application is perfectly valid for types: State s a really means (State s) a, so we can set m = State s:
instance Monad' (State s) where
-- return' :: a -> m a (where m = State s)
-- return' :: a -> State s a
return' x = State { runState = \s -> (x,s) }
-- bind' :: m a -> (a -> m b) -> m b (where m = State s)
-- bind' :: State s a -> (a -> State s b) -> State s b
bind' st f =
-- Good so far: we have two arguments
-- st :: State s a
-- f :: a -> State s b
-- We also need a result
-- ... :: State s b
-- It must be a State, so we can start with:
State { runState = \s ->
-- Now we also have
-- s :: s
-- That means we can run st:
let (x, s') = runState st s in
-- runState :: State s a -> s -> (a, s)
-- st :: State s a
-- s :: s
-- x :: a
-- s' :: s
-- Now we have a value of type 'a' that we can pass to f:
-- f x :: State s b
-- We are already in a State { ... } context, so we need
-- to return a (value, state) tuple. We can get that from
-- 'State s b' by using runState again:
runState (f x) s'
}
Have a look to this. Summing and extending a bit.
If you have a function
ta -> tb
and want to add "state" to it, then you should pass that state along, and have
(ta, ts) -> (tb, ts)
You can transform this by currying it:
ta -> ts -> (tb, ts)
If you compare this with the original ta -> tb, we obtain (adding parentheses)
ta -> (ts -> (tb, ts))
Summing up, if a function returns tb from ta (i.e. ta -> tb), a "stateful"
version of it will return (ts -> (tb, ts)) from ta (i.e. ta -> (ts -> (tb, ts)))
Therefore, a "stateful computation" (just one function, or either a chain of functions dealing with state) must return/produce this:
(ts -> (tb, ts))
This is the typical case of a stack of ints.
[Int] is the State
pop :: [Int] -> (Int, [Int]) -- remove top
pop (v:s) -> (v, s)
push :: Int -> [Int] -> (int, [Int]) -- add to the top
push v s -> (v, v:s)
For push, the type of push 5 is the same than type of pop :: [Int] -> (Int, [Int]).
So we would like to combine/join this basic operations to get things as
duplicateTop =
v <- pop
push v
push v
Note that, as desired, duplicateTop :: [Int] -> (Int, [Int])
Now: how to combine two stateful computations to get a new one?
Let's do it (Caution: this definition is not the same that the
used for the bind of monad (>>=) but it is equivalent).
Combine:
f :: ta -> (ts -> (tb, ts))
with
g :: tb -> (ts -> (tc, ts))
to get
h :: ta -> (ts -> (tc, ts))
This is the construction of h (in pseudo-haskell)
h = \a -> ( \s -> (c, s') )
where we have to calculate (c, s') (the rest in the expressions are just parameters a and s). Here it is how:
-- 1. run f using a and s
l1 = f a -- use the parameter a to get the function (ts -> (tb, ts)) returned by f
(b, s1) = l1 s -- use the parameter s to get the pair that l1 returns ( :: (tb, ts) )
-- 2. run g using f output, b and s1
l2 = g b -- use b to get the function (ts -> (tb, ts)) returned by g
(c, s') = l2 s1 -- use s1 to get the pair that l2 returns ( :: (tc, ts) )
Related
I came across the paper "https://www.cs.ox.ac.uk/jeremy.gibbons/publications/iterator.pdf" which has code examples in quite an abstract pseudo haskell syntax.
I'm struggeling to implement the example from section 6.2. in real haskell.
This is how far I came:
module Iterator where
import Data.Functor.Const -- for Const
import Data.Monoid (Sum (..), getSum) -- for Sum
import Control.Monad.State.Lazy -- for State
import Control.Applicative -- for WrappedMonad
data Prod m n a = Prod {pfst:: m a, psnd:: n a} deriving (Show)
instance (Functor m, Functor n) => Functor (Prod m n) where
fmap f (Prod m n) = Prod (fmap f m) (fmap f n)
instance (Applicative m, Applicative n) => Applicative (Prod m n) where
pure x = Prod (pure x) (pure x)
mf <*> mx = Prod (pfst mf <*> pfst mx) (psnd mf <*> psnd mx)
-- Functor Product
x :: (Functor m, Functor n) => (a -> m b) -> (a -> n b) -> (a -> Prod m n b)
(f `x` g) y = Prod (f y) (g y)
type Count = Const (Sum Integer)
count :: a -> Count b
count _ = Const 1
cciBody :: Char -> Count a
cciBody = count
cci :: String -> Count [a]
cci = traverse cciBody
lciBody :: Char -> Count a
lciBody c = Const (Sum $ test (c == '\n'))
test :: Bool -> Integer
test b = if b then 1 else 0
lci :: String -> Count [a]
lci = traverse lciBody
clci :: String -> Prod Count Count [a]
clci = traverse (cciBody `x` lciBody)
-- up to here the code is working
-- can't get this to compile:
wciBody :: Char -> (WrappedMonad (Prod (State Bool) Count)) a
wciBody c = pure $ state (updateState c) where
updateState :: Char -> Bool -> (Integer, Bool)
updateState c w = let s = c /= ' ' in (test (not(w && s)), s)
wci :: String -> (WrappedMonad (Prod (State Bool) Count)) [a]
wci = traverse wciBody
clwci :: String -> (Prod (Prod Count Count) (WrappedMonad (Prod (State Bool) Count))) [a]
clwci = traverse (cciBody `x` lciBody `x` wciBody)
str :: [Char]
str = "hello \n nice \t and \n busy world"
iteratorDemo = do
print $ clci str
print $ clwci str
The problematic spot is wciBody where I have no idea how to implement the ⇑ function from the paper.
Any ideas?
I think you may be mis-translating between the infix type operators used in the paper with the prefix type constructors in your definitions. I say this because the paper contains
wciBody :: Char → (𝕄 (State Bool) ⊡ Count) a
You have translated this as
wciBody :: Char -> (WrappedMonad (Prod (State Bool) Count)) a
which I don't think makes sense: Prod x y has no Monad instance, so it makes no sense to wrap it in WrapMonad. Rather, you are intended to read the ⊡ character as separating its entire left half (𝕄 (State Bool)) from its right half (Count), similar to how value-level operators in Haskell parse:
wciBody :: Char -> Prod (WrappedMonad (State Bool)) Count a
This makes more sense, doesn't it? Prod now takes three arguments, the first two of which are each of kind * -> *, and WrappedMonad's argument is clearly a monad. Does this change get you back on track?
Thanks to the hint by amalloy I finally got the example code working.
Here is what I came up with:
module Iterator where
import Data.Functor.Product -- Product of Functors
import Data.Functor.Compose -- Composition of Functors
import Data.Functor.Const -- Const Functor
import Data.Functor.Identity -- Identity Functor (needed for coercion)
import Data.Monoid (Sum (..), getSum) -- Sum Monoid for Integers
import Control.Monad.State.Lazy -- State Monad
import Control.Applicative -- WrappedMonad
import Data.Coerce (coerce) -- Coercion magic
-- Functor Product
(<#>) :: (Functor m, Functor n) => (a -> m b) -> (a -> n b) -> (a -> Product m n b)
(f <#> g) y = Pair (f y) (g y)
-- Functor composition
(<.>) :: (Functor m, Functor n) => (b -> n c) -> (a -> m b) -> (a -> (Compose m n) c)
f <.> g = Compose . fmap f . g
type Count = Const (Sum Integer)
count :: a -> Count b
count _ = Const 1
cciBody :: Char -> Count a
cciBody = count
cci :: String -> Count [a]
cci = traverse cciBody
lciBody :: Char -> Count a
lciBody c = Const $ test (c == '\n')
test :: Bool -> Sum Integer
test b = Sum $ if b then 1 else 0
lci :: String -> Count [a]
lci = traverse lciBody
clci :: String -> Product Count Count [a]
clci = traverse (cciBody <#> lciBody)
wciBody :: Char -> Compose (WrappedMonad (State Bool)) Count a
wciBody c = coerce (updateState c) where
updateState :: Char -> Bool -> (Sum Integer, Bool)
updateState c w = let s = not(isSpace c) in (test (not w && s), s)
isSpace :: Char -> Bool
isSpace c = c == ' ' || c == '\n' || c == '\t'
wci :: String -> Compose (WrappedMonad (State Bool)) Count [a]
wci = traverse wciBody
clwci :: String -> (Product (Product Count Count) (Compose (WrappedMonad (State Bool)) Count)) [a]
clwci = traverse (cciBody <#> lciBody <#> wciBody)
-- | the actual wordcount implementation.
-- for any String a triple of linecount, wordcount, charactercount is returned
wc :: String -> (Integer, Integer, Integer)
wc str =
let raw = clwci str
cc = coerce $ pfst (pfst raw)
lc = coerce $ psnd (pfst raw)
wc = coerce $ evalState (unwrapMonad (getCompose (psnd raw))) False
in (lc,wc,cc)
pfst :: Product f g a -> f a
pfst (Pair fst _) = fst
psnd :: Product f g a -> g a
psnd (Pair _ snd) = snd
main = do
putStrLn "computing three counters in one go"
print $ wc "hello \n world"
I am trying to understand the concept of Monad by attempting to write generic version of functions that might be then include side effects to log, change state.
Here is what I came up with: (The code is bit long, but it is there to show how I approached understanding monad - and this approach may not be correct)
data Maybe' a = Nothing' | Just' a deriving Show
sqrt' :: (Floating a, Ord a) => a -> Maybe' a
sqrt' x = if x < 0 then Nothing' else Just' (sqrt x)
inv' :: (Floating a, Ord a) => a -> Maybe' a
inv' x = if x == 0 then Nothing' else Just' (1/x)
log' :: (Floating a, Ord a) => a -> Maybe' a
log' x = if x == 0 then Nothing' else Just' (log x)
sqrtInvLog' :: (Floating a, Ord a) => a -> Maybe' a
sqrtInvLog' x = case (sqrt' x) of
Nothing' -> Nothing'
(Just' y) -> case (inv' y) of
Nothing' -> Nothing'
(Just' z) -> log' z
-- Now attempt to simplify the nested case:
fMaybe' :: (Maybe' a) -> (a -> Maybe' b) -> Maybe' b
fMaybe' Nothing' _ = Nothing'
fMaybe' (Just' x) f = f x
-- using fMaybe':
sqrtInvLog'' :: (Floating a, Ord a) => a -> Maybe' a
sqrtInvLog'' x = (sqrt' x) `fMaybe'` (inv') `fMaybe'` (log')
-- now we can generalize the concept to any type, instead of just Maybe' by defining a Monad =>
class Monad' m where
bind' :: m a -> (a -> m b) -> m b
return' :: a -> m a
instance Monad' Maybe' where
bind' Nothing' _ = Nothing'
bind' (Just' x) f = f x
return' x = Just' x
-- using Monad sqrtInvLog'' can be written as:
sqrtInvLog''' :: (Floating a, Ord a) => a -> Maybe' a
sqrtInvLog''' x = (sqrt' x) `bind'` (inv') `bind'` (log')
-- Further lets attempt to use this for state maintenence and logging, logging:
-- first attempt the specific version:
data ST a = ST (a, Maybe' a) deriving Show
sqrtSt :: (Floating a, Ord a)=> a -> a -> ST a
sqrtSt st x = let r = sqrt' x in case r of
Nothing' -> ST (st, Nothing')
(Just' y) -> ST (st+y, (Just' y))
invSt :: (Floating a, Ord a)=> a -> a -> ST a
invSt st x = let r = inv' x in case r of
Nothing' -> ST (st, Nothing')
(Just' y) -> ST (st+y, (Just' y))
logSt :: (Floating a, Ord a)=> a -> a -> ST a
logSt st x = let r = log' x in case r of
Nothing' -> ST (st, Nothing')
(Just' y) -> ST (st+y, (Just' y))
-- let us first define function which is similar to bind and manipulates the state and invokes the given function:
stBind :: (Floating a, Ord a) => ST a -> (a->a->ST a) -> ST a
stBind (ST (a, Nothing')) _ = ST (a, Nothing')
stBind (ST (s, (Just' y))) f = f s y
sqrtInvLogSt :: (Floating a, Ord a) => a -> a -> ST a
sqrtInvLogSt st x = (sqrtSt st x) `stBind` (invSt) `stBind` (logSt)
-- stBind does not fit the pattern of bind
-- Another version:
sqrtSt' :: (Floating a, Ord a)=> ST a -> ST a
sqrtSt' (ST (st, Nothing')) = ST (st, Nothing')
sqrtSt' (ST (st, (Just' x))) = let r = sqrt' x in case r of
Nothing' -> ST (st, Nothing')
(Just' y) -> ST (st+y, (Just' y))
invSt' :: (Floating a, Ord a)=> ST a -> ST a
invSt' (ST (st, Nothing')) = ST (st, Nothing')
invSt' (ST (st, (Just' x))) = let r = inv' x in case r of
Nothing' -> ST (st, Nothing')
(Just' y) -> ST (st+y, (Just' y))
logSt' :: (Floating a, Ord a)=> ST a -> ST a
logSt' (ST (st, Nothing')) = ST (st, Nothing')
logSt' (ST (st, (Just' x))) = let r = log' x in case r of
Nothing' -> ST (st, Nothing')
(Just' y) -> ST (st+y, (Just' y))
-- define stBind' here
stBind' :: (Floating a, Ord a) => ST a -> (ST a->ST a) -> ST a
stBind' (ST (a, Nothing')) _ = ST (a, Nothing')
stBind' stx f = f stx
sqrtInvLogSt' :: (Floating a, Ord a) => ST a->ST a
sqrtInvLogSt' stx = (sqrtSt' stx) `stBind'` (invSt') `stBind'` (logSt')
-- Even this does not fit the pattern of bind,
The function stBind' defined in the end does not fit the pattern of bind'.
How can I come up with an implementation in this situation to match the bind operator signature?
At the risk of spoilers, it might be interesting to peak at the definition of the State monad as it existed before everything became transformer-ified:
newtype State s a = State { runState :: s -> (a, s) }
That is: a stateful action with state s that produces a value of type a is a function from the old state s to a value and a new state, (a, s).
Starting from the correct definition for State should make the remainder of your development easier to puzzle through.
Given a simple "language":
data Expr a where
ConstE :: a -> Expr a
FMapE :: (b -> a) -> Expr b -> Expr a
instance Functor Expr where
fmap = FMapE
interpret :: Expr a -> a
interpret (ConstE a) = a
interpret (FMapE f a) = f (interpret a)
From that I would like to extract a call graph, eg:
foo = fmap show . fmap (*2) $ ConstE 1
Should result in the graph Node 1 -> Node (*2) -> Node show. Ideally I'd like to store this in a Data.Graph.
What I've come up to this point is that it should be possible to use System.Mem.StableNames to identify individual nodes and store them in a HashMap (StableName (Expr a)) (Expr a).
toHashMap :: Expr a -> HashMap (StableName (Expr a)) (Expr a)
toHashMap n#ConstE = do
sn <- makeStableName n
return $ HashMap.singleton sn n
The problem is, that there seems to be no way to get through the FMapE nodes:
toHashMap n#(FMapE _ a) = do
snN <- makeStableName n
snA <- makeStableName a
-- recurse
hmA <- toHashMap a
-- combine
return $ HashMap.singleton snN n `HashMap.union` hmA
GHC will complain along the lines of this:
Couldn't match type ‘t’ with ‘b’
because type variable ‘b’ would escape its scope
This (rigid, skolem) type variable is bound by
a pattern with constructor
FMapE :: forall a b. (b -> a) -> Expr b -> Expr a,
in an equation for ‘toHashMap’
I can see that this won't match ... but I have no clue on how to make this work.
Edit
This probably boils down to writing a children function:
children :: Event a -> [Event a]
children (ConstE) = []
children (FMapE _ a) = [a] -- doesn't match ...
For the same reason I can't uniplate on this ...
You can get a postorder traversal, which is a tolopogical sort for a tree, of a type of kind * -> * from the Uniplate1 class I've described previously.
{-# LANGUAGE RankNTypes #-}
import Control.Applicative
import Control.Monad.Identity
class Uniplate1 f where
uniplate1 :: Applicative m => f a -> (forall b. f b -> m (f b)) -> m (f a)
descend1 :: (forall b. f b -> f b) -> f a -> f a
descend1 f x = runIdentity $ descendM1 (pure . f) x
descendM1 :: Applicative m => (forall b. f b -> m (f b)) -> f a -> m (f a)
descendM1 f a = uniplate1 a f
transform1 :: Uniplate1 f => (forall b. f b -> f b) -> f a -> f a
transform1 f = f . descend1 (transform1 f)
transform1 is a generic postorder tranformation. A generic postorder Monadic traversal of a Uniplate1 is
transformM1 :: (Uniplate1 f, Applicative m, Monad m) =>
(forall b. f b -> m (f b)) ->
f a -> m (f a)
transformM1 f = (>>= f) . descendM1 (transformM1 f)
We can write a Uniplate1 instance for Expr:
instance Uniplate1 Expr where
uniplate1 e p = case e of
FMapE f a -> FMapE f <$> p a
e -> pure e
We'll make a simple dump function for demonstration purposes and bypass to restore the data after a monadic effect.
dump :: Expr b -> IO ()
dump (ConstE _) = putStrLn "ConstE"
dump (FMapE _ _) = putStrLn "FMapE"
bypass :: Monad m => (a -> m ()) -> a -> m a
bypass f x = f x >> return x
We can traverse your example in topological order
> transformM1 (bypass dump) (fmap show . fmap (*2) $ ConstE 1)
ConstE
FMapE
FMapE
I was reviewing some code and came across the following gem, which I'd wager is a copy-paste of pointfree output:
(I thought the following would more appropriate than the usual foo/bar for this particular question :P)
import Control.Monad (liftM2)
data Battleship = Battleship { x :: Int
, y :: Int
} deriving Show
placeBattleship :: Int -> Int -> Battleship
placeBattleship x' y' = Battleship { x = x', y = y' }
coordinates :: Battleship -> (Int, Int)
coordinates = liftM2 (,) x y
Would someone be kind enough to explain the steps needed to simplify from: (i) coordinates b = (x b, y b) to: (ii) coordinates = liftM2 (,) x y? In particular, I'm a bit confused as to the use of liftM2 as I wasn't even aware that a monad was lurking in the background.
I know that (i) can also be represented as: coordinates s = (,) (x s) (y s) but I'm not sure where/how to proceed.
P.S. The following is why I suspect it's from pointfree (output is from GHCI and :pl is aliased to pointfree):
λ: :pl coordinates s = (x s, y s)
coordinates = liftM2 (,) x y
This takes advantage of the Monad instance for (->) r, also called the "reader monad". This is the monad of functions from a specific type to a. (Take a look here for motivation on why it exists in the first place.)
To see how it works for various functions, replace m with (r -> in m a. For example, if we just do liftM, we get:
liftM :: (a -> b) -> (m a -> m b)
liftM :: (a -> b) -> ((r -> a) -> (r -> b))
:: (a -> b) -> (r -> a) -> (r -> b) -- simplify parentheses
...which is just function composition. Neat.
We can do the same thing for liftM2:
liftM2 :: (a -> b -> c) -> m a -> m b -> m c
liftM2 :: (a -> b -> c) -> (r -> a) -> (r -> b) -> (r -> c)
So what we see is a way to compose two one-argument functions with a two-argument function. It's a way of generalizing normal function composition to more than one argument. The idea is that we create a function that takes a single r by passing that through both of the one-argument functions, getting two arguments to pass into the two-argument function. So if we have f :: (r -> a), g :: (r -> b) and h :: (a -> b -> c), we produce:
\ r -> h (f r) (h r)
Now, how does this apply to your code? (,) is the two-argument function, and x and y are one-argument functions of the type Battleship -> Int (because that's how field accessors work). With this in mind:
liftM2 (,) x y = \ r -> (,) (x r) (y r)
= \ r -> (x r, y r)
Once you've internalized the idea of multiple function composition like this, point-free code like this becomes quite a bit more readable—no need to use the pointfree tool! In this case, I think the non-pointfree version is still better, but the pointfree one isn't terrible itself.
The monad liftM2 is working over here is the function monad (->) a. This is equivalent to the Reader monad, as you may have seen before.
Recall the definition of liftM2:
liftM2 :: Monad m => (a -> b -> r) -> m a -> m b -> m r
liftM2 f ma mb = do
a <- ma
b <- mb
return $ f a b
So now if we substitute in (,) for f, x for ma, and y for mb, we get
liftM2 (,) x y = do
a <- x
b <- y
return $ (,) a b
Since x, y :: Battleship -> Int which is equivalent to ((->) Battleship) Int, then m ~ (->) Battleship. The function monad is defined as
instance Monad ((->) a) where
return x = const x
m >>= f = \a -> f (m a) a
Essentially what the function monad does is allow you to extract the output from several functions provided they all have the same input. A more clear example might be something like
test = do
a <- (^2)
b <- (^3)
c <- (^4)
d <- show
return (a, b, c, d)
> test 2
(4, 8, 16, "2")
You could easily rewrite
data Battleship = Battleship { x :: Int
, y :: Int
} deriving Show
placeBattleship :: Int -> Int -> Battleship
placeBattleship x y = Battleship x y
coordinates :: Battleship -> (Int, Int)
coordinates (Battleship x y) = (x, y)
It isn't point-free style, but quite simple
After reading (and skimming some sections of) Wadler's paper on monads, I decided to work through the paper more closely, defining functor and applicative instances for each of the monads he describes. Using the type synonym
type M a = State -> (a, State)
type State = Int
Wadler uses to define the state monad, I have the following (using related names so I can define them with a newtype declaration later on).
fmap' :: (a -> b) -> M a -> M b
fmap' f m = \st -> let (a, s) = m st in (f a, s)
pure' :: a -> M a
pure' a = \st -> (a, st)
(<#>) :: M (a -> b) -> M a -> M b
sf <#> sv = \st -> let (f, st1) = sf st
(a, st2) = sv st1
in (f a, st2)
return' :: a -> M a
return' a = pure' a
bind :: M a -> (a -> M b) -> M b
m `bind` f = \st -> let (a, st1) = m st
(b, st2) = f a st1
in (b, st2)
When I switch to using a type constructor in a newtype declaration, e.g.,
newtype S a = S (State -> (a, State))
everything falls apart. Everything is just a slight modification, for instance,
instance Functor S where
fmap f (S m) = S (\st -> let (a, s) = m st in (f a, s))
instance Applicative S where
pure a = S (\st -> (a, st))
however nothing runs in GHC due to the fact that the lambda expression is hidden inside that type constructor. Now the only solution I see is to define a function:
isntThisAnnoying s (S m) = m s
in order to bind s to 'st' and actually return a value, e.g.,
fmap f m = S (\st -> let (a, s) = isntThisAnnoying st m in (f a, s))
Is there another way to do this that doesn't use these auxiliary functions?
If you look here, you will see that they define it this way:
newtype State s a = State { runState :: (s -> (a,s)) }
so as to give the inner lambda a name.
The usual way is to define newtype newtype S a = S {runState : State -> (a, State)}. Then instead of your isntThisAnnoying s (S m) you can write runState t s where t is the same as S m.
You have to use a newtype because type synonyms cannot be typeclass instances.