GHCi ignores type signature - haskell

Prelude> let myprint = putStrLn . show
Prelude> :t myprint
myprint :: () -> IO ()
OK, nothing too unusual here. Just GHCi type defaulting rules, I guess...
Prelude> let myprint = (putStrLn . show) :: Show x => x -> IO ()
Prelude> :t myprint
myprint :: () -> IO ()
What sorcery is this?? You're point-blank ignoring my type declaration?! O_O
Is there some way I can convince GHCi to do what I actually intended?

Adding a type annotation to an expression as in
e :: type
makes the compiler check that e has that type, as well as use that type to drive type variables instantiation and instance selection. However, if the type is polymorphic it can still be instantiated later on. Consider e.g.
(id :: a -> a) "hello"
Above, a will be instantiated to String, despite my annotation. Further,
foo :: Int -> Int
foo = (id :: a -> a)
will make a to be instantiated to Int later on. The above id annotation does not give any information to GHC: it already knows that id has that type.
We could remove it without affecting the type checking at all. That is, the expressions id and id :: a->a are not only dynamically equivalent, but also statically such.
Similarly, the expressions
putStrLn . show
and
(putStrLn . show) :: Show x => x -> IO ()
are statically equivalent: we are just annotating the code with the type GHC can infer. In other words, we are not providing any information to GHC it does not already know.
After the annotation is type checked, GHC can then instantiate x further. The monomorphism restriction does that in your example. To prevent that, use an annotation for the binding you are introducing, not for the expression:
myprint :: Show x => x -> IO ()
myprint = (putStrLn . show)

We can do the following, with monomorphism restriction on:
>let myprint :: Show x => x -> IO (); myprint = putStrLn . show
>:t myprint
myprint :: Show x => x -> IO ()
This is not the same as let myprint = putStrLn . show :: Show x => x -> IO (). In the former case we have a binding with a type signature, in the latter case we a have a let binding with a type annotation inside the right hand side. Monomorphism checks top-level type signatures, but not local annotations.

Related

Haskell cast higher kinded types

This code is compiling:
trigger :: (Typeable n) => n () -> IO ()
trigger n = case (cast n) of
Just n' -> n'
Nothing -> error "n is not IO"
But if I add parenthesis it doesn't anymore:
-- not compiling
trigger' :: (forall n. (Typeable n) => n ()) -> IO ()
trigger' n = case (cast n) of
Just n' -> n'
Nothing -> error "n is not IO"
It says "No instance for (Typeable n) arising from a use of ‘cast’".
Why?
In practice I need the second form because in my program I use data types that have forall:
data Foo = Foo {a :: (Typeable n) => n ()}
trigger' :: Foo -> IO ()
trigger' (Foo n) = case (cast n) of
Just n' -> n'
Nothing -> error "n is not IO"
trigger :: (Typeable n) => n () -> IO ()
"For any n that is Typeable, I can turn a n () into an IO ()
trigger' :: (forall n. (Typeable n) => n ()) -> IO ()
"I can turn a value which can typed n () for every n that is Typeable into an IO ()"
The second doesn't really make sense; there are no values of the required type to give it (other than undefined). Even if there were, there would be no need to use cast; since the argument can be assigned every n () type you can just return it as is; it's already an IO () as a special case of being every n (), so you shouldn't even need trigger (except perhaps to pin down an ambiguous type). This is almost certainly not what you want.
The first signature is what you would need if you had an existential type; if you can build Foos containing any n () (provided it's Typeable), and you later want to be able to run them if they happen to contain an IO (). I suspect that this is actually what you want, and you have accidentally defined your data type incorrectly, rather than the problem being in trigger.
Consider this:
{-# LANGUAGE GADTs, RankNTypes #-}
module Foo where
import Data.Typeable (Typeable, cast)
data Foo = Foo { a :: Typeable n => n () }
data Bar = Bar { bar :: forall n. Typeable n => n () }
data Baz = forall n. Typeable n => Baz { baz :: n () }
trigger :: Typeable n => n () -> IO ()
trigger n = case (cast n) of
Just n' -> n'
Nothing -> error "n is not IO"
Your Foo is equivalent to Bar, not to Baz:
λ :t Foo
Foo :: (forall (n :: * -> *). Typeable n => n ()) -> Foo
*Foo
λ :t Bar
Bar :: (forall (n :: * -> *). Typeable n => n ()) -> Bar
*Foo
λ :t Baz
Baz :: Typeable n => n () -> Baz
The implicit forall is placed at the beginning of the type signature of the field a, rather than quantifying over the whole constructor. Consequently you've asked that the field a is forall n. Typeable n => n (), instead of the constructor working on any n () and the field containing some particular but unknown n ().
And we can see that Baz works with trigger the way you seem to want it to:
*Foo
λ case Baz (putStrLn "yay") of Baz x -> trigger x
yay
it :: ()
While for Foo, if you can get its field out you can use it directly as an IO () without needing any cast, but there's no way to actually put something into a Foo in the first place:
λ case Foo undefined of Foo x -> putStrLn "weird" >> x
weird
*** Exception: Prelude.undefined
Because "weird" is actually printed you can see that the type-checker accepted this expression; it was perfectly fine with the idea that the hypothetical contents of a Foo would be usable as an IO (), with no need for trigger at all. But I've handwaved-away the problem actually constructing a Foo in the first place; it's basically impossible without using something like undefined. This is what makes me think it's your data declaration that is incorrect, rather than trigger.
But if there's something about your real use-case that makes the data type wrapping a polymorphic field more reasonable (if there were more constraints than Typeable it could be possible to use), and it also doesn't work to simply dispense with trigger and make use of the contained polymorphism to "cast" to a more specific type, then we'll need more information to address your actual use case.

When is a generic function not generic?

I'm working on a Haskell server using scotty and persistent. Many handlers need access to the database connection pool, so I've taken to passing the pool around throughout the app, in this sort of fashion:
main = do
runNoLoggingT $ withSqlitePool ":memory:" 10 $ \pool ->
liftIO $ scotty 7000 (app pool)
app pool = do
get "/people" $ do
people <- liftIO $ runSqlPool getPeople pool
renderPeople people
get "/foods" $ do
food <- liftIO $ runSqlPool getFoods pool
renderFoods food
where getPeople and getFoods are appropriate persistent database actions that return [Person] and [Food] respectively.
The pattern of calling liftIO and runSqlPool on a pool becomes tiresome after a while - wouldn't it be great if I could refactor them into a single function, like Yesod's runDB, which would just take the query and return the appropriate type. My attempt at writing something like this is:
runDB' :: (MonadIO m) => ConnectionPool -> SqlPersistT IO a -> m a
runDB' pool q = liftIO $ runSqlPool q pool
Now, I can write this:
main = do
runNoLoggingT $ withSqlitePool ":memory:" 10 $ \pool ->
liftIO $ scotty 7000 $ app (runDB' pool)
app runDB = do
get "/people" $ do
people <- runDB getPeople
renderPeople people
get "/foods" $ do
food <- runDB getFoods
renderFoods food
Except that GHC complains:
Couldn't match type `Food' with `Person'
Expected type: persistent-2.1.1.4:Database.Persist.Sql.Types.SqlPersistT
IO
[persistent-2.1.1.4:Database.Persist.Class.PersistEntity.Entity
Person]
Actual type: persistent-2.1.1.4:Database.Persist.Sql.Types.SqlPersistT
IO
[persistent-2.1.1.4:Database.Persist.Class.PersistEntity.Entity
Food]
In the first argument of `runDB', namely `getFoods'
It seems like GHC is saying that in fact the type of runDB becomes specialised somehow. But then how are functions like runSqlPool defined? Its type signature looks similar to mine:
runSqlPool :: MonadBaseControl IO m => SqlPersistT m a -> Pool Connection -> m a
but it can be used with database queries that return many different types, as I was doing originally. I think there's something fundamental I'm misunderstanding about types here, but I have no idea how to find out what it is! Any help would be greatly appreciated.
EDIT:
at Yuras' suggestion, I've added this:
type DBRunner m a = (MonadIO m) => SqlPersistT IO a -> m a
runDB' :: ConnectionPool -> DBRunner m a
app :: forall a. DBRunner ActionM a -> ScottyM ()
which required -XRankNTypes for the typedef. However, the compiler error is still identical.
EDIT:
Victory to the commentors. This allows the code to compile:
app :: (forall a. DBRunner ActionM a) -> ScottyM ()
For which I'm grateful, but still mystified!
The code is currently looking like this and this.
It seems like GHC is saying that in fact the type of runDB becomes specialised somehow.
Your guess is right. Your original type was app :: (MonadIO m) => (SqlPersistT IO a -> m a) -> ScottyM (). This means that your runDB argument of type SqlPersistT IO a -> m a can be used at any one type a. However, the body of app wants to use the runDB argument at two different types (Person and Food) so instead we need to pass an argument that can work for any number of different types in the body. Thus app needs the type
app :: MonadIO m => (forall a. SqlPersistT IO a -> m a) -> ScottyM ()
(I would suggest keeping the MonadIO constraint outside the forall but you can also put it inside.)
EDIT:
What's going on behind the scenes is the following:
(F a -> G a) -> X means forall a. (F a -> G a) -> X, which means /\a -> (F a -> G a) -> X. /\ is the type-level lambda. That is, the caller gets to pass in a single type a and a function of type F a -> G a for that particular choice of a.
(forall a. F a -> G a) -> X means (/\a -> F a -> G a) -> X and the caller has to pass in a function which the callee can specialise to many choices of a.
Lets play the game:
Prelude> let f str = (read str, read str)
Prelude> f "1" :: (Int, Float)
(1,1.0)
Works as expected.
Prelude> let f str = (read1 str, read1 str) where read1 = read
Prelude> f "1" :: (Int, Float)
(1,1.0)
Works too.
Prelude> let f read1 str = (read1 str, read1 str)
Prelude> f read "1" :: (Int, Float)
<interactive>:21:1:
Couldn't match type ‘Int’ with ‘Float’
Expected type: (Int, Float)
Actual type: (Int, Int)
In the expression: f read "1" :: (Int, Float)
In an equation for ‘it’: it = f read "1" :: (Int, Float)
But this doesn't. What the difference?
The last f has the next type:
Prelude> :t f
f :: (t1 -> t) -> t1 -> (t, t)
So it doesn't work for clear reason, both elements of the tuple should have the same type.
The fix is like that:
Prelude> :set -XRankNTypes
Prelude> let f read1 str = (read1 str, read1 str); f :: (Read a1, Read a2) => (forall a . Read a => str -> a) -> str -> (a1, a2)
Prelude> f read "1" :: (Int, Float)
(1,1.0)
Unlikely I can come with good explanation of RankNTypes, so I'd not even try. There is enough resources in web.
To really answer the title question that apparently continues to mystify you: Haskell always chooses the most generic rank-1 type for a function, when you don't supply an explicit signature. So for app in the expression app (runDB' pool), GHC would attempt to have type
app :: DBRunner ActionM a -> ScottyM ()
which is in fact shorthand for
app :: forall a. ( DBRunner ActionM a -> ScottyM () )
This is rank-1 polymorphic, because all type variables are introduced outside of the signature (there is no quantification going on in the signature itself; the argument DBRunner ActionM a is in fact monomorphic since a is fixed at that point). Actually, it is the most generic type possible: it can work with a polymorphic argument like (runDB' pool), but would also be ok with monomorphic arguments.
But it turns out the implementation of app can't offer that generality: it needs a polymorphic action, otherwise it can't feed two different types of a values to that action. Therefore you need to manually request the more specific type
app :: (forall a. DBRunner ActionM a) -> ScottyM ()
which is rank-2, because it has a signature which contains a rank-1 polymorphic argument. GHC can't really know this is the type you want – there's no well defined “most general possible rank-n type” for an expression, since you can always push in extra quantifiers. So you must manually specify the rank-2 type.

Monomorphism restriction in pattern bindings

{-# LANGUAGE NoMonomorphismRestriction #-}
module Try where
f :: IO (a -> IO String)
f = return $ const getLine
main :: IO ()
main = do
g <- f
:: IO (a -> IO String)
g "String" >>= print
g 5 >>= print
Even with the NoMonomorphismRestriction flag and explicit type signature, this module fails to compile with Couldn't match expected type ‘[Char]’ with actual type ‘Int’, despite g being fully polymorphic.
This is not what the monomorphism restriction means. The monomorphism restriction says that if a definition has no type signature and has a left-hand side with no parameters, it will be specialized to a monomorphic type (or rather just monomorphic enough to get rid of any class constraints). You have given type signatures so it doesn't apply.
The problem here is that you have given the wrong type to f.
f :: IO (a -> IO String)
actually means
f :: forall a. IO (a -> IO String)
That is, first pick a type a, then you can bind to get a monomorphic function of type a -> IO String for that a. There is no trouble with this program, for example:
main = do
g <- f
g "String" >>= print
g' <- f
g' 5 >>= print
But your usage example requires this type:
f :: IO (forall a. a -> IO String)
That is, you want to bind first and pick the type later, i.e. use the function at multiple types. This is called an "impredicative type" and unfortunately GHC has not supported them for quite a while, as far as I know.
The way to solve this problem is to make a newtype wrapper that explicitly quantifies the inner polymorphic type:
newtype R = R { getR :: forall a. a -> IO String }
f :: IO R
f = return $ R (const getLine)
main :: IO ()
main = do
g <- f
getR g "String" >>= print
getR g 5 >>= print

GHC: Why does type ambiguity go away when using let

I have a type class
class (Monad f) => Test f where
test :: () -> f ()
and an instance
instance Test (ErrorT String (Identity)) where
test pat = return pat
If I run a monad stack referring to this instance, GHC can't find out what monad I am talking about (in a do block of the Either String monad):
rhs' <- runIdentity $ runErrorT $ test rhs
yields the error message:
Ambiguous type variable `f0' in the constraint:
(Test f0) arising from a use of `test'
...
But if I bind the part test rhs to a variable:
let action = test rhs
rhs' <- runIdentity $ runErrorT $ action
it works, even though the variable is used nowhere else so nothing new can be inferred about it.
How is this possible, if I have added no information for the type checker to use? Why can't it figure out the type of the equivalent first formulation? Or are the two formulations not equivalent? What part of the Haskell type checker (or desugaring rules?) did I not understand here?
I am using the extensions MultiParamTypeClasses, FlexibleInstances and ScopedTypeVariables
edit: I simplified the example so the strange issue occurs without needing the rest of my code (and with a shorter monad stack), but now it looks nonsensical. The full context of the statement is:
doStuff :: (Map Int ()) -> Either String (Map Int ())
doStuff g = run (snd . head . Map.toList $ g) g where
run :: () -> Map Int () -> Either String (Map Int ())
run rhs g = do
let action = test rhs
rhs' <- runIdentity $ runErrorT $ test rhs -- or: action
return g
The code
doStuff :: (Map Int ()) -> Either String (Map Int ())
doStuff g = run (snd . head . Map.toList $ g) g where
run :: () -> Map Int () -> Either String (Map Int ())
run rhs g = do
rhs' <- runIdentity $ runErrorT $ test rhs
return g
or
doStuff :: (Map Int ()) -> Either String (Map Int ())
doStuff g = run (snd . head . Map.toList $ g) g where
run :: () -> Map Int () -> Either String (Map Int ())
run rhs g = do
let action = test rhs
rhs' <- runIdentity $ runErrorT $ action
return g
should type check without issue. The problem is
doStuff :: (Map Int ()) -> Either String (Map Int ())
doStuff g = run (snd . head . Map.toList $ g) g where
run :: () -> Map Int () -> Either String (Map Int ())
run rhs g = do
let action = test rhs
rhs' <- runIdentity $ runErrorT $ action
return g
the reason for this is that you seem to have MonoLocalBinds or the Monomorphism Restriction enabled which prevents generalizations of the binding to action unless the type is known.
It seems that the Monomorphism Restriction tripped me up, together with the fact that I left the unused binding in the code when switching between the two versions (I thought I didn't and it wouldn't matter, but it did). So the type of action could not be inferred down to a monomorphic type.
There is still an open issue: In my original code, I use a Polymorphic type (Pattern s) everywhere you now see (). The compiler suggests in the error message that I add a type signature for action to fix the polymorphism, but confusingly I can't: Even with ScopedTypeVariables I get the error message Couldn't match type 's1' with 's3' ... about rigid type variables bound in the type signatures for run and action. But I guess that is another question, so I consider this one answered. Thank you.

What make the difference between `:t` and let expression in GHCi

I want to make a toy function that produces a Maybe a and then lift show to make it a Maybe String, but the outcome was weird for me:
λ> :t liftM show . Just
liftM show . Just :: Show a1 => a1 -> Maybe String
λ> liftM show . Just $ 10
Just "10"
λ> let f = liftM show . Just
λ> f 10
<interactive>:9:3:
No instance for (Num ()) arising from the literal `10'
Possible fix: add an instance declaration for (Num ())
In the first argument of `f', namely `10'
In the expression: f 10
In an equation for `it': it = f 10
λ> :t f
f :: () -> Maybe String
λ> let g = liftM show . Just :: (Show a) => a -> Maybe String
λ> :t g
g :: () -> Maybe String
λ> let h = liftM show . Just :: Int -> Maybe String
λ> :t h
h :: Int -> Maybe String
I guess it has something to do with type inference, but I really don't know what happened:
where did that mysterious () come from?
why GHCi didn't complain about ambiguousness?
Dum-duuum!
Next victim of the dreaded monomorphism restriction.
What happens is this: for a definition that looks like a "constant variable" (in the sense that other languages might also use, i.e. not of function type), like f = ..., it is assumed that you wish it to actually behave like a constant (CAF, to be precise). That means, it must not be polymorphic, since with parametric polymorphism there's basically an extra implicit argument to the function (the information which type a1 should be).
To achieve this actual-const-ness, ghci defaults this type variable to whatever specific type it deems least inappropriate. Here, the only constraint is Show; the simplest type fulfilling that is ().
The "correct" way of getting around this is to turn off the monomorphism restriction:
Prelude> :set -XNoMonomorphismRestriction
Prelude> :m +Control.Monad
Prelude Control.Monad> let f = liftM show . Just
Prelude Control.Monad> f 10
Just "10"
Alternatively, you can, like in an actual source file you always should, give proper signatures to identifiers in ghci:
Prelude Control.Monad> let g :: Show a => a -> Maybe String; g = liftM show . Just
Prelude Control.Monad> g 10
Just "10"
Doing that only on the RHS of the = doesn't work, since the monomorphism restriction kicks in only after that is resolved and defaults away the variables (unless, as in h, there are no variables in the first place because you gave a monomorphic signature to the RHS).
Still another thing you can do, simply give the function an explicit argument, then the monomorphism restriction doesn't apply at all. I.e., write it non–point-free:
Prelude Control.Monad> let i a = liftM show $ Just a
Prelude Control.Monad> i 10
Just "10"

Resources