Haskell lens: let binding of Traversal' - haskell

I'm a bit confused and don't know where to look for the information/explanation of the following "issue" (it's not an issue per se, but more of a situation where I don't understand what is wrong behind the scenes):
I have a monad transformer stack with StateT. At some point in my function I would like to bind a small fraction of my state into the local variable so I can refer to it instead of writing out the whole path to the chunk of the state I'm interested in. Here is what I mean:
{-# LANGUAGE ScopedTypeVariables #-}
...
someFunction :: MyMonad ()
someFunction = do
...
let x :: Traversal' MyState MyDataT = myState.clients.ix clientIdx.someData.ix dataIdx
...
Now this doesn't compile:
Couldn't match type ‘(MyDataT -> f0 MyDataT)
-> MyState -> f0 MyState’
with ‘forall (f :: * -> *).
Control.Applicative.Applicative f =>
(MyDataT -> f MyDataT) -> MyState -> f MyState’
But if I move the referencing of this data chunk into a function then everything compiles ok:
someFunction :: MyMonad ()
someFunction = do
...
let x = clientData clientIdx dataIdx
...
where clientData :: Int -> Int -> Traversal' MyState MyDataT
clientData clientIdx dataIdx = myState.clients.ix clientIdx.someData.ix dataIdx
I'm looking for some kind of information that will help me understand what is going on here, why it happens, so that I'm aware of what I'm doing wrong. Basically I would like to expand my knowledge to understand this use case a bit better.

The key point here is that the annotation should be in a separate line. If we do that, then we have a binding with an explicit type, as far as GHC is concerned.
someFunction :: MyMonad ()
someFunction = do
...
let x :: Traversal' MyState MyDataT
x = myState.clients.ix clientIdx.someData.ix dataIdx
...
What you first tried very rarely works as you intended:
let x :: Traversal' MyState MyDataT = ...
This is a binding without an explicit type; the annotation is inside the left hand side. GHC considers the type of the variable fixed before looking at the right hand side, but the annotation only applies to the left hand side, so GHC just infers a type for the right had side separately, and then tries to match it exactly with the annotation. This makes the type checking fail for all but the simplest non-polymorphic cases.
The right way of putting annotations inside bindings is the following:
let x = ... :: Traversal' MyState MyDataT
Here, GHC first assigns a "malleable" indeterminate type variable to x, then infers a type for the right side informed by the annotation there, then unifies the type of x with it.
This is still a binding without an explicit type, but it works in general if we enable NoMonomorphismRestriction, for reasons detailed in this SO question.

Related

How to pattern match on an universally quantified free monad?

I'm wondering if I can write a function isPure :: Free f () -> Bool, which tells you if the given free monad equals Pure () or not. This is easy to do for a simple case, but I can't figure it out for a more complex case where there are constraints on the functor f.
import Control.Monad.Free
-- * This one compiles
isPure :: Free Maybe () -> Bool
isPure (Pure ()) = True
isPure _ = False
-- * This one fails to compile with "Ambiguous type variable ‘context0’ arising from a pattern
-- prevents the constraint ‘(Functor context0)’ from being solved."
{-# LANGUAGE RankNTypes #-}
type ComplexFree = forall context. (Functor context) => Free context ()
isPure' :: ComplexFree -> Bool
isPure' (Pure ()) = True
isPure' _ = False
I can see why specifying the exact type of context0 would be necessary in general, but all I want is to look the coarse-grained structure of the free monad (i.e. is it Pure or not Pure). I don't want to pin down the type because my program relies on passing around some constrained universally quantified free monads and I want this to work with any of them. Is there some way to do this? Thanks!
EDITED to change "existentially quantified" -> "universally quantified"
EDIT: since my ComplexFree type might have been too general, here's a version that more exactly mimics what I'm trying to do.
--* This one actually triggers GHC's warning about impredicative polymorphism...
{-# LANGUAGE GADTs #-}
data MyFunctor context next where
MyFunctor :: Int -> MyFunctor context next -- arguments not important
type RealisticFree context a = Free (MyFunctor context) a
class HasFoo context where
getFoo :: context -> Foo
class HasBar context where
getBar :: context -> Bar
type ConstrainedRealisticFree = forall context. (HasFoo context, HasBar context) => RealisticFree context ()
processRealisticFree :: ConstrainedRealisticFree -> IO ()
processRealisticFree crf = case isPure'' crf of
True -> putStrLn "It's pure!"
False -> putStrLn "Not pure!"
isPure'' :: ConstrainedRealisticFree -> Bool
isPure'' = undefined -- ???
(For some more context, this free monad is meant to model an interpreter for a simple language, where a "context" is present. You can think of the context as describing a reader monad that the language is evaluated within, so HasFoo context and HasBar context enforce that a Foo and Bar are available. I use universal quantification so that the exact type of the context can vary. My goal is to be able to identify an "empty program" in this free monad interpreter.)
First of all, this is not existential quantification. That would look like this:
data ComplexFree = forall context. (Functor context) => ComplexFree (Free context ())
(a syntax I find rather confusing, so I prefer the GADT form
data ComplexFree where
ComplexFree :: (Functor context) => Free context () -> ComplexFree
, which means the same thing)
You have a universally quantified type here, that is, if you have a value of type ComplexFree (the way you have written it), it can turn into a free monad over any functor you choose. So you can just instantiate it at Identity, for example
isPure' :: ComplexFree -> Bool
isPure' m = case m :: Free Identity () of
Pure () -> True
_ -> False
It must be instantiated at some type in order to inspect it, and the error you see is because the compiler couldn't decide which functor to use by itself.
However, instantiating is not necessary for defining isPure'. Ignoring bottoms1, one of the functors you could instantiate ComplexFree with is Const Void, which means that the recursive case of Free reduces to
f (m a)
= Const Void (m a)
~= Void
that is, it is impossible. By some naturality arguments, we can show that which branch a ComplexFree takes cannot depend on the choice of functor, which means that any fully-defined ComplexFree must be a Pure one. So we can "simplify" to
isPure' :: ComplexFree -> Bool
isPure' _ = True
How boring.
However, I suspect you may have made a mistake defining ComplexFree, and you really do want the existential version?
data ComplexFree where
ComplexFree :: (Functor context) => Free context () -> ComplexFree
In this case, a ComplexFree "carries" the functor with it. It only works for one functor, and it (and only it) knows what functor that is. This problem is better-formed, and implemented just as you would expect
isPure' :: ComplexFree -> Bool
isPure' (ComplexFree (Pure _)) = True
isPure' _ = False
1 Ignoring bottom is a common practice, and usually not problematic. This reduction strictly increases the information content of the program -- that is, whenever the original version gave a defined answer, the new version will give the same answer. But the new one might "fail to go into an infinite loop" and accidentally give an answer instead. In any case, this reduction can be modified to be completely correct, and the resulting isPure' is just as useless.
I'll answer your revamped question here. It turns out that the answer is still basically the same as luqui's: you need to instantiate the polymorphic argument before you can pattern match on it. Thanks to the constraint, you need to use a context type that's an instance of the relevant classes. If it would be inconvenient to use a "real" one, you can easily make a throw-away:
data Gump = Gump Foo Bar
instance HasFoo Gump where
getFoo (Gump f _) = f
instance HasBar Gump where
getBar (Gump _ b) = b
That should be fine for this particular case. However, in most similar practical situations, you'll want to instantiate to your real type to get its specialized behavior.
Now you can instantiate the context to Gump and you're good to go:
isPure'' :: ConstrainedRealisticFree -> Bool
isPure'' q = case q :: RealisticFree Gump () of
Pure _ -> True
Free _ -> False
The reason you got that error about impredicative types is that you wrote
isPure'' = ...
Higher-rank polymorphic parameters are generally required to be syntactically parameters:
isPure'' q = ...

Haskell: How to write a type of function from a specific type to any type?

In Scala, I could write the following trait:
trait Consumer[A] {
def apply(a: A): Unit
}
And scala would convert whatever I want to Unit, i.e., it would discard the type. Equivalently, I could have said that apply returns Any and ignore the result.
However, in Haskell, if I defined the type as type Consumer = a -> IO (), I wouldn't be able to pass an Int -> IO Int function, as Int isn't ().
There are two ways I know of solving this issue, but none are satisfactory:
Use Data.Functor.void at the call site to manual change IO a to IO (). This is annoying as an API user.
define type Consumer a b = a -> IO b, but then every time I would want to use Consumer in a signature, I would have to carry the useless type b.
Is there any way to define the Consumer type as a function from a to "IO Any"? As far as I know, Haskell does not support something like exists x. a -> IO x.
Using forall results in the opposite of what I want, e.g.,
type Consumer = forall b. a -> IO b
foo :: Int -> IO Int
foo = undefined
bar :: Consumer Int
bar = foo
results in the error:
• Couldn't match type ‘b’ with ‘Int’
‘b’ is a rigid type variable bound by
the type signature for:
bar :: Consumer Int
Expected type: Int -> IO b
Actual type: Int -> IO Int
• In the expression: foo
In an equation for ‘bar’: bar = foo
• Relevant bindings include
bar :: Int -> IO b
Note that I specifically want Consumer to a be type alias, and not a data constructor, as is described here: Haskell function returning existential type. I wouldn't mind if Consumer were a class if anyone knows how to make that work.
To get an existentially-quantified type in Haskell, you need to write down a data declaration (as opposed to a newtype declaration or a type alias declaration, like you used.).
Here's a Consumer type that fits your purposes:
{-# LANGUAGE ExistentialQuantification #-}
data Consumer input = forall output. Consumer { runDiscardingOutput :: input -> IO output }
And, analogously, here is what your example would look like with the new type:
f :: Int -> IO Int
f = undefined
g :: Consumer Int
g = Consumer f
This doesn't really avoid your concerns about client code needing an extra call, though. (I mean, this is no better than exporting a consumer = Data.Functor.void binding from your library.) Also, it complicates how clients will be able to use a consumer, too:
consumer :: Consumer Int
consumer = Consumer (\x -> return [x])
{- This doesn't typecheck -}
main1 :: IO ()
main1 = runIgnoringOutput consumer 4
{- This doesn't typecheck (!!!) -}
main2 :: IO ()
main2 = void (runIgnoringOutput consumer 4)
{- Only this typechecks :( -}
main3 :: IO ()
main3 =
case consumer of
Consumer f -> Data.Functor.void (f 4)
So it would probably make sense to have a apply function in your library that did the dirty work, just as there was an apply function in the Scala library.
apply :: Consumer a -> a -> IO ()
apply (Consumer f) x = void (f x)
I wouldn't mind if Consumer were a class if anyone knows how to make that work.
You can simulate existential types for classes with an associated type family.
But Haskell doesn't allow ambiguous types in classes without using something like a GADT existential wrapper, so you would still have the type information there somewhere.
{-# LANGUAGE TypeFamilies, MultiParamTypeClasses #-}
class Consumer c a where
type Output c
consume :: c -> a -> IO (Output c)
c is necessary here to allow for the reconstruction of the type of Output c, so it is not strictly an existential. But you can now write
{-# LANGUAGE FlexibleInstances, InstanceSigs #-}
instance Consumer (a -> IO b) a where
type Output (a -> IO b) = b
consume :: (a -> IO b) -> a -> IO b
consume = id
This may not fit your use case, because there will not be a type signature that can express Consumer a in a truly existential way. But it is possible to write
... :: (Consumer c a) => c -> ...
(You could also make use of FunctionalDependencies here to clarify the class somewhat.)

'Referencing' typeclass functions

I'm a beginner and I'm trying to use Hoed to trace Haskell evaluations, because maybe it will further help my learning process.
I saw in their examples code like this
isEven :: Int -> Bool
isEven = observe "isEven" isEven'
isEven' n = mod2 n == 0
I was thinking how could I observe in order to trace an instance defined function like >>= for example.
I wrote something like
bind' = observe "bind'" (>>=)
and of course I've got an error
* Ambiguous type variable 'm0' arising from a use of '>>='
prevents the constraint '(Monad m0)' from being solved.
Relevant bindings include
bind' :: m0 a0 -> (a0 -> m0 b0) -> m0 b0 (bound at my.hs:46:1)
Probable fix: use a type annotation to specify what 'm0' should be.
These potential instances exist:
...
Should I / How could I use a type annotation in order to specify which Monad instance's (e.g. Reader, State etc.) >>= function
It looks like you have found the infamous MonomorphismRestriction. More info. The links do a great job of explaining what the MonomorphismRestriction is and how it works.
You're not wrong to expect that writing bind' with no signature should "just work". However, sometimes the compiler needs a bit of help. In short, due to the MonomorphismRestriction, GHC tries to take the nominally polymorphic signature of bind' :: Monad m => m a -> (a -> m b) -> m b, and make it less polymorphic by instantiating some of the type variables.
In your case, it looks like the compiler wants to make bind' only work for one specific Monad m. Without your real code, I can't say for sure, but consider this example:
import Debug.Trace
main :: IO ()
main = (>>=) (return "hello") print
bind' = trace "bind" (>>=)
The compiler produces an error similar to yours: Ambiguous type variable m0
However, if you use bind':
import Debug.Trace
main :: IO ()
main = bind' (return "hello") print
bind' = trace "bind" (>>=)
no error! That's because GHC is inferring that m should be IO since bind' is used in the IO monad.
Alternatively, you can tell GHC to turn off the MonomorphismRestriction:
{-# LANGUAGE NoMonomorphismRestriction #-}
import Debug.Trace
main :: IO ()
main = (>>=) (return "hello") print
bind' = trace "bind" (>>=)
and it compiles just fine!

STRef and phantom types

Does s in STRef s a get instantiated with a concrete type? One could easily imagine some code where STRef is used in a context where the a takes on Int. But there doesn't seem to be anything for the type inference to give s a concrete type.
Imagine something in pseudo Java like MyList<S, A>. Even if S never appeared in the implementation of MyList instantiating a concrete type like MyList<S, Integer> where a concrete type is not used in place of S would not make sense. So how can STRef s a work?
tl;dr - in practice it seems it always gets initialised to RealWorld in the end
The source notes that s can be instantiated to RealWorld inside invocations of stToIO, but is otherwise uninstantiated:
-- The s parameter is either
-- an uninstantiated type variable (inside invocations of 'runST'), or
-- 'RealWorld' (inside invocations of 'Control.Monad.ST.stToIO').
Looking at the actual code for ST however it seems runST uses a specific value realWorld#:
newtype ST s a = ST (STRep s a)
type STRep s a = State# s -> (# State# s, a #)
runST :: (forall s. ST s a) -> a
runST st = runSTRep (case st of { ST st_rep -> st_rep })
runSTRep :: (forall s. STRep s a) -> a
runSTRep st_rep = case st_rep realWorld# of
(# _, r #) -> r
realWorld# is defined as a magic primitive inside the GHC source code:
realWorldName = mkWiredInIdName gHC_PRIM (fsLit "realWorld#")
realWorldPrimIdKey realWorldPrimId
realWorldPrimId :: Id -- :: State# RealWorld
realWorldPrimId = pcMiscPrelId realWorldName realWorldStatePrimTy
(noCafIdInfo `setUnfoldingInfo` evaldUnfolding
`setOneShotInfo` stateHackOneShot)
You can also confirm this in ghci:
Prelude> :set -XMagicHash
Prelude> :m +GHC.Prim
Prelude GHC.Prim> :t realWorld#
realWorld# :: State# RealWorld
From your question I can not see if you understand why the phantom s type is there at all. Even if you did not ask for this explicitly, let me elaborate on that.
The role of the phantom type
The main use of the phantom type is to constrain references (aka pointers) to stay "inside" the ST monad. Roughly, the dynamically allocated data must end its life when runST returns.
To see the issue, let's pretend that the type of runST were
runST :: ST s a -> a
Then, consider this:
data Dummy
let var :: STRef Dummy Int
var = runST (newSTRef 0)
change :: () -> ()
change = runST (modifySTRef var succ)
access :: () -> Int
result :: (Int, ())
result = (access() , change())
in result
(Above I added a few useless () arguments to make it similar to imperative code)
Now what should be the result of the code above? It could be either (0,()) or (1,()) depending on the evaluation order. This is a big no-no in the pure Haskell world.
The issue here is that var is a reference which "escaped" from its runST. When you escape the ST monad, you are no longer forced to use the monad operator >>= (or equivalently, the do notation to sequentialize the order of side effects. If references are still around, then we can still have side effects around when there should be none.
To avoid the issue, we restrict runST to work on ST s a where a does not depend on s. Why this? Because newSTRef returns a STRef s a, a reference to a tagged with the phantom type s, hence the return type depends on s and can not be extracted from the ST monad through runST.
Technically, this restriction is done by using a rank-2 type:
runST :: (forall s. ST s a) -> a
the "forall" here is used to implement the restriction. The type is saying: choose any a you wish, then provide a value of type ST s a for any s I wish, then I will return an a. Mind that s is chosen by runST, not by the caller, so it could be absolutely anything. So, the type system will accept an application runST action only if action :: forall s. ST s a where s is unconstrained, and a does not involve s (recall that the caller has to choose a before runST chooses s).
It is indeed a slightly hackish trick to implement the independence constraint, but it does work.
On the actual question
To connect this to your actual question: in the implementation of runST, s will be chosen to be any concrete type. Note that, even if s were simply chosen to be Int inside runST it would not matter much, because the type system has already constrained a to be independent from s, hence to be reference-free. As #Ganesh pointed out, RealWorld is the type used by GHC.
You also mentioned Java. One could attempt to play a similar trick in Java as follows: (warning, overly simplified code follows)
interface ST<S,A> { A call(); }
interface STAction<A> { <S> ST<S,A> call(S dummy); }
...
<A> A runST(STAction<A> action} {
RealWorld dummy = new RealWorld();
return action.call(dummy).call();
}
Above in STAction parameter A can not depend on S.

Writing a function with a universally-quantified return type

If I write
foo :: (Num a) => a
foo = 42
GHC happily accepts it, but if I write
bar :: (Num a) => a
bar = (42 :: Int)
it tells me that the expected type a doesn't match the inferred type Int. I don't quite understand why, since Int is an instance of the class Num that a stands for.
I'm running into this same situation while trying to write a function that, boiled down to the core of the problem, looks roughly like this:
-- Note, Frob is an instance of class Frobbable
getFrobbable :: (Frobbable a) => Frob -> a
getFrobbable x = x
Is it possible to write a function like this? How can I make the result compatible with the type signature?
You are treating typeclass constraints as if they were subtype constraints. This is a common thing to do, but in fact they only coincide in the contravariant case, that is, when concerning function arguments rather than results. The signature:
bar :: (Num a) => a
Means that the caller gets to choose the type a, provided that it is an instance of Num. So here, the caller may choose to call bar :: Int or bar :: Double, they should all work. So bar :: (Num a) => a must be able to construct any kind of number, bar does not know what specific type was chosen.
The contravariant case is exactly the same, it just corresponds with OO programmers' intuition in this case. Eg.
baz :: (Num a) => a -> Bool
Means that the caller gets to choose the type a, again, and again baz does not know what specific type was chosen.
If you need to have the callee choose the result type, just change the signature of the function to reflect this knowledge. Eg.:
bar :: Int
Or in your getFrobbable case, getFrobbable :: Frob -> Frob (which makes the function trivial). Anywhere that a (Frobbable a) constraint occurs, a Frob will satisfy it, so just say Frob instead.
This may seem awkward, but it's really just that information hiding happens at different boundaries in functional programming. There is a way to hide the specific choice, but it is uncommon, and I consider it a mistake in most cases where it is used.
One way to get the effect your sample seems to be going for
I first want to describe a way to accomplish what it appears you're going for. Let's look at your last code sample again:
-- Note, Frob is an instance of class Frobbable
getFrobbable :: (Frobbable a) => Frob -> a
getFrobbable x = x
This is essentially a casting operation. It takes a Frob and simply forgets what it is, retaining only the knowledge that you've got an instance of Frobbable.
There is an idiom in Haskell for accomplishing this. It requires the ExistentialQuantification extension in GHC. Here is some sample code:
{-# LANGUAGE ExistentialQuantification #-}
module Foo where
class Frobbable a where
getInt :: a -> Int
data Frob = Frob Int
instance Frobbable Frob where
getInt (Frob i) = i
data FrobbableWrapper = forall a . Frobbable a => FW a
instance Frobbable FrobbableWrapper where
getInt (FW i) = getInt i
The key part is the FrobbableWrapper data structure. With it, you can write the following version of your getFrobbable casting function:
getFrobbable :: Frobbable a => a -> FrobbableWrapper
getFrobbable x = FW x
This idiom is useful if you want to have a heterogeneous list whose elements share a common typeclass, even though they may not share a common type. For instance, while Frobbable a => [a] wouldn't allow you to mix different instances of Frobbable, the list [FrobbableWrapper] certainly would.
Why the code you posted isn't allowed
Now, why can't you write your casting operation as-is? It's all about what could be accomplished if your original getFrobbable function was permitted to type check.
The equation getFrobbable x = x really should be thought of as an equation. x isn't being modified in any way; thus, neither is its type. This is done for the following reason:
Let's compare getFrobbable to another object. Consider
anonymousFrobbable :: Frobbable a => a
anonymousFrobbable = undefined
(Code involving undefined are a great source of awkward behavior when you want to really push on your intuition.)
Now suppose someone comes along and introduces a data definition and a function like
data Frob2 = Frob2 Int Int
instance Frobbable Frob2 where
getInt (Frob2 x y) = y
useFrobbable :: Frob2 -> [Int]
useFrobbable fb2 = []
If we jump into ghci we can do the following:
*Foo> useFrobbable anonymousFrobbable
[]
No problems: the signature of anonymousFrobbable means "You pick an instance of Frobbable, and I'll pretend I'm of that type."
Now if we tried to use your version of getFrobbable, a call like
useFrobbable (getFrobbable someFrob)
would lead to the following:
someFrob must be of type Frob, since it is being given to getFrobbable.
(getFrobbable someFrob) must be of type Frob2 since it is being given to useFrobbable
But by the equation getFrobbable someFrob = someFrob, we know that getFrobbable someFrob and someFrob have the same type.
Thus the system concludes that Frob and Frob2 are the same type, even though they are not. Hence this reasoning is unsound, which is ultimately the type of rational behind why the version of getFrobbable you posted doesn't type-check.
Also worth noting is that the literal 42 actually stands for fromInteger (42 :: Integer), which really has type (Num a) => a. See the Haskell Report on numeric literals.
A similar mechanism works for floating point numbers and you can get GHC to use overloaded string literals, but for other types there is (to my knowledge) no way to do that.
I am a teensy bit confused as to what you're trying to do, but if you just want the caller's use of the return value to drive instance selection, then that's normal typeclasses at work.
data Frob = Frob Int Float
class FrobGettable a where
getFrobbable :: Frob -> a
instance FrobGettable Int where
getFrobbable (Frob x _) = x
instance FrobGettable Float where
getFrobbable (Frob _ y) = y
instance FrobGettable Char where
getFrobbable _ = '!'
frob = Frob 10 3.14
test1 :: Float
test1 = getFrobbable frob * 1.1
test2 :: Int
test2 = getFrobbable frob `div` 4
test3 = "Hi" ++ [getFrobbable frob]
We can use GHCi to see what we have,
*Main> :t getFrobbable
getFrobbable :: (FrobGettable a) => Frob -> a

Resources