Why doesn't this typecheck? - haskell

This is toy-example.hs:
{-# LANGUAGE ImpredicativeTypes #-}
import Control.Arrow
data From = From (forall a. Arrow a => a Int Char -> a [Int] String)
data Fine = Fine (forall a. Arrow a => a Int Char -> a () String)
data Broken = Broken (Maybe (forall a. Arrow a => a Int Char -> a () String))
fine :: From -> Fine
fine (From f) = Fine g
where g :: forall a. Arrow a => a Int Char -> a () String
g x = f x <<< arr (const [1..5])
broken :: From -> Broken
broken (From f) = Broken (Just g) -- line 17
where g :: forall a. Arrow a => a Int Char -> a () String
g x = f x <<< arr (const [1..5])
And this is what ghci thinks of it:
GHCi, version 7.0.3: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Loading package ffi-1.0 ... linking ... done.
Prelude> :l toy-example.hs
[1 of 1] Compiling Main ( toy-example.hs, interpreted )
toy-example.hs:17:32:
Couldn't match expected type `forall (a :: * -> * -> *).
Arrow a =>
a Int Char -> a () String'
with actual type `a0 Int Char -> a0 () String'
In the first argument of `Just', namely `g'
In the first argument of `Broken', namely `(Just g)'
In the expression: Broken (Just g)
Failed, modules loaded: none.
Why does fine typecheck while broken does not?
How do I get broken to typecheck?
(In my real code I can add the type parameter a to Broken if I have to, instead of having it universally quantified inside the constructor, but I'd like to avoid this if possible.)
Edit: If I change the definition of Broken to
data Broken = Broken (forall a. Arrow a => Maybe (a Int Char -> a () String))
then broken typechecks. Yay!
But if I then add the following function
munge :: Broken -> String
munge (Broken Nothing) = "something" -- line 23
munge (Broken (Just f)) = f chr ()
then I get the error message
toy-example.hs:23:15:
Ambiguous type variable `a0' in the constraint:
(Arrow a0) arising from a pattern
Probable fix: add a type signature that fixes these type variable(s)
In the pattern: Nothing
In the pattern: Broken Nothing
In an equation for `munge': munge (Broken Nothing) = "something"
How do I get munge to typecheck as well?
2nd edit: In my real program I have replaced the Broken (Maybe ...) constructor with BrokenNothing and BrokenJust ... constructors (there were already other constructors), but I'm curious how pattern matching is supposed to work in this situation.

ImpredicativeTypes leaves you on quite shaky ground that changes from GHC version to version in any case - they're struggling to find a formulation of impredicativity that appropriately balances power, ease of use and ease of implementation.
In this particular case, trying to put a quantified type inside a Maybe, which is a datatype not explicitly defined to behave this way, is really tricky, so I'd advise going for the custom-defined constructors instead as you mention.
I think that you can fix munge above by re-deconstructing the argument to Broken on the RHS, at a time when the type its being used as will be known, e.g.:
munge (Broken x#(Just _)) = fromJust x chr ()
It's pretty ugly, though.

Related

Haskell syb Data.Generics not working as expected

On a ghci prompt everywhere (mkT (\x -> 2 * x)) (8.7, 21, "word") evaluates to (8.7, 42, "word").
I expected the 8.7 to be doubled as well. Why am I wrong?
This is the result of mkT monomorphizing its argument in this particular case, but it turns out there's no broader way to address the issue. mkT isn't doing anything wrong.
It's worth looking first at why everywhere (* 2) doesn't type-check.
ghci> :t everywhere
everywhere
:: (forall a. Data a => a -> a) -> forall a. Data a => a -> a
ghci> :t (* 2)
(* 2) :: Num a => a -> a
ghci> :t everywhere (* 2)
<interactive>:1:13: error:
• Could not deduce (Num a) arising from a use of ‘*’
from the context: Data a
bound by a type expected by the context:
forall a. Data a => a -> a
at <interactive>:1:12-16
Possible fix:
add (Num a) to the context of
a type expected by the context:
forall a. Data a => a -> a
• In the expression: (*)
In the first argument of ‘everywhere’, namely ‘(* 2)’
In the expression: everywhere (* 2)
everywhere has a higher-rank type - the first forall a. is inside the parentheses. I kind of dislike documenting the type that way - it uses a as a type variable in two completely separate ways. But there are two different scopes, and that matters. What it's saying is that any function passed to it must be polymorphic over all instances of Data.
But the type of (* 2) doesn't match up there. It won't work with any instance of Data. It requires more - it requires that it be provided an instance of Num. So the error message dutifully reports that it can't deduce (Num a) from the context Data a. So this isn't going to work. The pieces don't fit together.
This is where mkT comes into play:
ghci> :t mkT
mkT :: (Typeable a, Typeable b) => (b -> b) -> a -> a
Its type is a bit funny. It looks almost like it does nothing at all, but Typeable is a funny class. mkT actually compares a and b for type equality, using those Typeable constraints. If they're the same, it applies the function you provided. Otherwise, it just acts as the identity function.
What it does when it's applied to a function is where things are going wrong for you:
ghci> :t mkT (* 2)
mkT (* 2) :: Typeable a => a -> a
It's still polymorphic in a, but the b it used to have has vanished. It had to pick a specific type b to work against, and it did that by defaulting to Integer. (See ghc's extended defaulting rules for details on how that works in ghci.) So...
ghci> mkT (* 2) 3.5
3.5
ghci> mkT (* 2) 7
14
ghci> mkT (* 2) (7 :: Int)
7
At the type level, mkT has to monomorphize its argument. That's the only way it can make use of the Typeable constraint when used in a context where a relevant variable no longer appears in its type.
(To tie the loop back to everywhere, the reason mkT (* 2) works as an argument to everywhere is because Data is a subclass of Typeable. The Data constraint implies that the Typeable requirement will be satisfied.)
So what can you do about this? Well, it's impossible to write it truly generically because of Haskell's open world assumption. Anywhere in the program, any type might be declared an instance of Num with arbitrary implementations of (*) and fromInteger. In order to work with everywhere, there would need to be some mechanism to go from knowing something is an instance of Data to looking up its Num instance. This just isn't possible at run time. Types have been erased. There may be some residues like Typeable dictionaries being carried around, but they don't provide any means to look up other instance dictionaries. And while you might be able to envision a language where that sort of lookup is possible, it actually would be very harmful to allow it in Haskell. It would invalidate the ability to reason about types parametrically, which would be a giant loss.
The best you can do is write transformation functions that work on multiple types:
ghci> let f = mkT (* (2 :: Int)) . mkT (* (2 :: Double)) . mkT (* (2 :: Integer))
ghci> f 5
10
ghci> f 2.7
5.4
ghci> f (9 :: Int)
18
ghci> f "hello"
"hello"
It's verbose and you can probably write something better by hand if you so desire. But it at least works, at least to some extent. And it doesn't require breaking foundational assumptions in the language design, which is always a bonus.
Here is a simplification of your case that doesn't use any Data stuff.
module MyModule where
dbl x = 2 * x
myId :: (a->a) -> a -> a
myId f = f
myDbl = myId dbl
Don't type this to the ghci prompt, rather, create a .hs file and load it.
Now check what type myDbl has.
Prelude > :l MyModule
[1 of 1] Compiling MyModule ( MyModule.hs, interpreted )
Ok, one module loaded.
*MyModule > :t MyModule.myDbl
MyModule.myDbl :: Integer -> Integer
Surprise! Why is it compiling at all? And why the weird types?
Because of the defaulting rules. (Basically, "if you don't know what to do with Num a, just use Integer"). Since myId cannot deal with dbl :: Num a => a -> a, Haskell allows it to take the Integer version.
Disable defaulting by adding default () at the top, and this module no longer compiles.
mkT is no different from myId in this respect.

Incomplete implicit type inference in Haskell

Let's consider the following example:
data A = A{x::Int} deriving(Show)
instance Func_f (A -> String) where
f _ = "ala"
class Func_f a where
f :: a
main :: IO ()
main = do
let
a = A 5
x = f a
print 5
compiled with ghc -XFlexibleInstances main.hs
(I've tried -XExtendedDefaultRules, but without any progress)
Why while compiling we get an error?:
main.hs:25:21:
No instance for (Func_f (A -> t0)) arising from a use of `f'
The type variable `t0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Note: there is a potential instance available:
instance Func_f (A -> String) -- Defined at main.hs:7:10
Possible fix: add an instance declaration for (Func_f (A -> t0))
In the expression: f a
In an equation for `x': x = f a
In the expression:
do { let a = A 5
x = f a;
print 5 }
There is only one instance for Func_f, so Haskell should be able to know the result of x = f a. You can fix the error by providing the type manually, like this: x = f a :: String, but this is not suitable for my case, because I'm generating Haskell code and I would love the Haskell's type inferencer to do this job for me.
You're running into the open world assumption. The basic idea is that GHC always assumes that you could add more class instances to your code. Moreover, you cannot control how instances get exported and imported between modules. So relying on only having one instance of a particular class is not going to work and would lead to weird bugs.
Essentially, nothing stops you--or anybody else, for that matter--from writing another instance like:
instance Func_f (A -> Int) where
f _ = 10
and it would then be impossible to figure out which one you wanted in your code. This could cause your code to break just from linking against another module!
However, if you actually used the value, chances are it would get its type constrained by some other parameter and the ambiguity would go away. For example, the following works:
main :: IO ()
main = do
let a = A 5
x = f a
putStr x
Basically, this is one of those cases (similar to read . show) where a type signature is simply unavoidable because of how GHC treats typeclass instances.
There is only one instance for Func_f, so Haskell should be able to know the result of x = f a
This violates the open world assumption.

Simple example for ImpredicativeTypes

The GHC user's guide describes the impredicative polymorphism extension with reference to the following example:
f :: Maybe (forall a. [a] -> [a]) -> Maybe ([Int], [Char])
f (Just g) = Just (g [3], g "hello")
f Nothing = Nothing
However, when I define this example in a file and try to call it, I get a type error:
ghci> f (Just reverse)
<interactive>:8:9:
Couldn't match expected type `forall a. [a] -> [a]'
with actual type `[a0] -> [a0]'
In the first argument of `Just', namely `reverse'
In the first argument of `f', namely `(Just reverse)'
In the expression: f (Just reverse)
ghci> f (Just id)
<interactive>:9:9:
Couldn't match expected type `forall a. [a] -> [a]'
with actual type `a0 -> a0'
In the first argument of `Just', namely `id'
In the first argument of `f', namely `(Just id)'
In the expression: f (Just id)
Seemingly only undefined, Nothing, or Just undefined satisfies the type-checker.
I have two questions, therefore:
Can the above function be called with Just f for any non-bottom f?
Can someone provide an example of a value only definable with impredicative polymorphism, and usable in a non-trivial way?
The latter is particularly with the HaskellWiki page on Impredicative Polymorphism in mind, which currently makes a decidedly unconvincing case for the existence of the extension.
Here's an example of how one project, const-math-ghc-plugin, uses ImpredicativeTypes to specify a list of matching rules.
The idea is that when we have an expression of the form App (PrimOp nameStr) (Lit litVal), we want to look up the appropriate rule based upon the primop name. A litVal will be either a MachFloat d or MachDouble d (d is a Rational). If we find a rule, we want to apply the function for that rule to d converted to the correct type.
The function mkUnaryCollapseIEEE does this for unary functions.
mkUnaryCollapseIEEE :: (forall a. RealFloat a => (a -> a))
-> Opts
-> CoreExpr
-> CoreM CoreExpr
mkUnaryCollapseIEEE fnE opts expr#(App f1 (App f2 (Lit lit)))
| isDHash f2, MachDouble d <- lit = e d mkDoubleLitDouble
| isFHash f2, MachFloat d <- lit = e d mkFloatLitFloat
where
e d = evalUnaryIEEE opts fnE f1 f2 d expr
The first argument needs to have a Rank-2 type, because it will be instantiated at either Float or Double depending on the literal constructor. The list of rules looks like this:
unarySubIEEE :: String -> (forall a. RealFloat a => a -> a) -> CMSub
unarySubIEEE nm fn = CMSub nm (mkUnaryCollapseIEEE fn)
subs =
[ unarySubIEEE "GHC.Float.exp" exp
, unarySubIEEE "GHC.Float.log" log
, unarySubIEEE "GHC.Float.sqrt" sqrt
-- lines omitted
, unarySubIEEE "GHC.Float.atanh" atanh
]
This is ok, if a bit too much boilerplate for my taste.
However, there's a similar function mkUnaryCollapsePrimIEEE. In this case, the rules are different for different GHC versions. If we want to support multiple GHCs, it gets a bit tricky. If we took the same approach, the subs definition would require a lot of CPP, which can be unmaintainable. Instead, we defined the rules in a separate file for each GHC version. However, mkUnaryCollapsePrimIEEE isn't available in those modules due to circular import issues. We could probably re-structure the modules to make it work, but instead we defined the rulesets as:
unaryPrimRules :: [(String, (forall a. RealFloat a => a -> a))]
unaryPrimRules =
[ ("GHC.Prim.expDouble#" , exp)
, ("GHC.Prim.logDouble#" , log)
-- lines omitted
, ("GHC.Prim.expFloat#" , exp)
, ("GHC.Prim.logFloat#" , log)
]
By using ImpredicativeTypes, we can keep a list of Rank-2 functions, ready to use for the first argument to mkUnaryCollapsePrimIEEE. The alternatives would be much more CPP/boilerplate, changing the module structure (or circular imports), or a lot of code duplication. None of which I would like.
I do seem to recall GHC HQ indicating that they would like to drop support for the extension, but perhaps they've reconsidered. It is quite useful at times.
Isn't it just that ImpredicativeTypes has been quietly dropped with the new typechecker in ghc-7+ ? Note that ideone.com still uses ghc-6.8 and indeed your program use to run fine :
{-# OPTIONS -fglasgow-exts #-}
f :: Maybe (forall a. [a] -> [a]) -> Maybe ([Int], [Char])
f (Just g) = Just (g [3], g "hello")
f Nothing = Nothing
main = print $ f (Just reverse)
prints Just ([3],"olleh") as expected; see http://ideone.com/KMASZy
augustss gives a handsome use case -- some sort of imitation Python dsl -- and a defense of the extension here: http://augustss.blogspot.com/2011/07/impredicative-polymorphism-use-case-in.html referred to in the ticket here http://hackage.haskell.org/trac/ghc/ticket/4295
Note this workaround:
justForF :: (forall a. [a] -> [a]) -> Maybe (forall a. [a] -> [a])
justForF = Just
ghci> f (justForF reverse)
Just ([3],"olleh")
Or this one (which is basically the same thing inlined):
ghci> f $ (Just :: (forall a. [a] -> [a]) -> Maybe (forall a. [a] -> [a])) reverse
Just ([3],"olleh")
Seems like the type inference has problems infering the type of the Just in your case and we have to tell it the type.
I have no clue if it's a bug or if there is a good reason for it.. :)

Haskell rank two polymorphism compile error

Given the following definitions:
import Control.Monad.ST
import Data.STRef
fourty_two = do
x <- newSTRef (42::Int)
readSTRef x
The following compiles under GHC:
main = (print . runST) fourty_two -- (1)
But this does not:
main = (print . runST) $ fourty_two -- (2)
But then as bdonlan points out in a comment, this does compile:
main = ((print . runST) $) fourty_two -- (3)
But, this does not compile
main = (($) (print . runST)) fourty_two -- (4)
Which seems to indicate that (3) only compiles due to special treatment of infix $, however, it still doesn't explain why (1) does compile.
Questions:
1) I've read the following two questions (first, second), and I've been led to believe $ can only be instantiated with monomorphic types. But I would similarly assume . can only be instantiated with monomorphic types, and as a result would similarly fail.
Why does the first code succeed but the second code does not? (e.g. is there a special rule GHC has for the first case that it can't apply in the second?)
2) Is there a current GHC extension that compiles the second code? (perhaps ImpredicativePolymorphism did this at some point, but it seems deprecated, has anything replaced it?)
3) Is there any way to define say `my_dollar` using GHC extensions to do what $ does, but is also able to handle polymorphic types, so (print . runST) `my_dollar` fourty_two compiles?
Edit: Proposed Answer:
Also, the following fails to compile:
main = ((.) print runST) fourty_two -- (5)
This is the same as (1), except not using the infix version of ..
As a result, it seems GHC has special rules for both $ and ., but only their infix versions.
I'm not sure I understand why the second doesn't work. We can look at the type of print . runST and observe that it is sufficiently polymorphic, so the blame doesn't lie with (.). I suspect that the special rule that GHC has for infix ($) just isn't quite sufficient. SPJ and friends might be open to re-examining it if you propose this fragment as a bug on their tracker.
As for why the third example works, well, that's just because again the type of ((print . runST) $) is sufficiently polymorphic; in fact, it's equal to the type of print . runST.
Nothing has replaced ImpredicativePolymorphism, because the GHC folks haven't seen any use cases where the extra programmer convenience outweighed the extra potential for compiler bugs. (I don't think they'd see this as compelling, either, though of course I'm not the authority.)
We can define a slightly less polymorphic ($$):
{-# LANGUAGE RankNTypes #-}
infixl 0 $$
($$) :: ((forall s. f s a) -> b) -> ((forall s. f s a) -> b)
f $$ x = f x
Then your example typechecks okay with this new operator:
*Main> (print . runST) $$ fourty_two
42
I can't say with too much authority on this subject, but here's what I think may be happening:
Consider what the typechecker has to do in each of these cases. (print . runST) has type Show b => (forall s. ST s t) -> IO (). fourty_two has type ST x Int.
The forall here is an existential type qualifier - here it means that the argument passed in has to be universal on s. That is, you must pass in a polymorphic type that supports any value for s whatsoever. If you don't explicitly state forall, Haskell puts it at the outermost level of the type definition. This means that fourty_two :: forall x. ST x Int and (print . runST) :: forall t. Show t => (forall s. ST s t) -> IO ()
Now, we can match forall x. ST x Int with forall s. ST s t by letting t = Int, x = s. So the direct call case works. What happens if we use $, though?
$ has type ($) :: forall a b. (a -> b) -> a -> b. When we resolve a and b, since the type for $ doesn't have any explicit type scoping like this, the x argument of fourty_two gets lifted out to the outermost scope in the type for ($) - so ($) :: forall x t. (a = forall s. ST s t -> b = IO ()) -> (a = ST x t) -> IO (). At this point, it tries to match a and b, and fails.
If you instead write ((print . runST) $) fourty_two, then the compiler first resolves the type of ((print . runST $). It resolves the type for ($) to be forall t. (a = forall s. ST s t -> b = IO ()) -> a -> b; note that since the second occurance of a is unconstrained, we don't have that pesky type variable leaking out to the outermost scope! And so the match succeeds, the function is partially applied, and the overall type of the expression is forall t. (forall s. ST s t) -> IO (), which is right back where we started, and so it succeeds.

Reflection on inputs to a function in Haskell?

I have a reflective situation where I want to display the types of inputs/outputs of a function. I could just add it to a separate data structure, but then I have duplication and would have to make sure they stay in sync manually.
For example, a function:
myFunc :: (String, MyType, Double) -> (Int, SomeType TypeP, MyOtherType a)
and so now I want to have something like (can be somewhat flexible, esp. when params involved):
input = ["String", "MyType", "Double"]
output = ["Int", "SomeType TypeP", "MyOtherType a"]
defined automatically. It doesn't have to be Strings directly. Is there a simple way to do this?
You don't really need a custom parser. You can just reflect on the TypeRep value you receive. For instance the following would work:
module ModuleReflect where
import Data.Typeable
import Control.Arrow
foo :: (Int, Bool, String) -> String -> String
foo = undefined
-- | We first want to in the case that no result is returned from splitTyConApp
-- to just return the input type, this. If we find an arrow constructor (->)
-- we want to get the start of the list and then recurse on the tail if any.
-- if we get anything else, like [] Char then we want to return the original type
-- [Char]
values :: Typeable a => a -> [TypeRep]
values x = split (typeOf x)
where split t = case first tyConString (splitTyConApp t) of
(_ , []) -> [t]
("->", [x]) -> [x]
("->", x) -> let current = init x
next = last x
in current ++ split next
(_ , _) -> [t]
inputs :: Typeable a => a -> [TypeRep]
inputs x = case values x of
(x:xs) | not (null xs) -> x : init xs
_ -> []
output :: Typeable a => a -> TypeRep
output x = last $ values x
and a sample session
Ok, modules loaded: ModuleReflect.
*ModuleReflect Data.Function> values foo
[(Int,Bool,[Char]),[Char],[Char]]
*ModuleReflect Data.Function> output foo
[Char]
*ModuleReflect Data.Function> inputs foo
[(Int,Bool,[Char]),[Char]]
This is just some quick barely tested code, I'm sure it can be cleaned up. And the reason I don't use typeRepArgs is that in the case of other constructors they would be broken up to, e.g [] Char returns Char instead of [Char].
This version does not treat elements of tuples as seperate results, but it can be easily changed to add that.
However as mentioned before this has a limitation, It'll only work on monomorphic types. If you want to be able to find this for any type, then you should probably use the GHC api. You can load the module, ask it to Typecheck and then inspect the Typecheck AST for the function and thus find it's type. Or you can use Hint to ask for the type of a function. and parse that.
Have a look at Data.Typeable: It defined a functiontypeOf :: Typeable a => a -> TypeRep, TypeRep is instance of Show. For example:
$ ghci
GHCi, version 6.12.1: http://www.haskell.org/ghc/ :? for help
:m Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude> :m +Data.Typeable
Prelude Data.Typeable> :i TypeRep
data TypeRep
= Data.Typeable.TypeRep !Data.Typeable.Key TyCon [TypeRep]
-- Defined in Data.Typeable
instance [overlap ok] Eq TypeRep -- Defined in Data.Typeable
instance [overlap ok] Show TypeRep -- Defined in Data.Typeable
instance [overlap ok] Typeable TypeRep -- Defined in Data.Typeable
Prelude Data.Typeable> typeOf (+)
Integer -> Integer -> Integer
Prelude Data.Typeable> typeOf (\(a,(_:x),1) -> (a :: (),x :: [()]))
((),[()],Integer) -> ((),[()])
Now, you only need a custom parser that translated this output into something suitable for you. This is left as an exercise to the reader.
PS: There seems to be one limitation: All types must be known before, for instance typeOf id will fail.

Resources