Haskell regex context ambiguous type despite explicit Bool type annotation, succeeds in ghci - haskell

This works in an interpreter session
λ> import Text.Regex.Base
λ> import Text.Regex.Posix
λ> import Data.List (sort)
λ> import System.Directory
λ> ls <- getDirectoryContents "."
λ> let csvs = sort $ filter (\x -> x =~ "csv$" :: Bool) ls
λ> recent = last csvs
This is great and gives me exactly what I need.
However, the same code fails to compile in a script:
t10.hs:40:35-45: error: …
• Ambiguous type variable ‘source0’ arising from a use of ‘=~’
prevents the constraint ‘(RegexMaker
Regex CompOption ExecOption source0)’ from being solved.
Probable fix: use a type annotation to specify what ‘source0’ should be.
These potential instances exist:
instance RegexMaker Regex CompOption ExecOption C.ByteString
-- Defined in ‘Text.Regex.Posix.ByteString’
instance RegexMaker Regex CompOption ExecOption LB.ByteString
-- Defined in ‘Text.Regex.Posix.ByteString.Lazy’
• In the expression: x =~ "csv$" :: Bool
In the first argument of ‘filter’, namely
‘(\ x -> x =~ "csv$" :: Bool)’
In the second argument of ‘($)’, namely
‘filter (\ x -> x =~ "csv$" :: Bool) ls’
t10.hs:40:40-45: error: …
• Ambiguous type variable ‘source0’ arising from the literal ‘"csv$"’
prevents the constraint ‘(Data.String.IsString
source0)’ from being solved.
Probable fix: use a type annotation to specify what ‘source0’ should be.
I have an explicit :: Bool context at the end to provide exactly this information. Why would this be succeeding in ghci but failing to catch this same instruction when compiling, and how can I fix it?

The ambiguity is not about what the type of x =~ "csv$" is - that is already determined from your use of filter. The problem is the "csv$" literal itself. Based on the error message, you have the OverloadedStrings language extension enabled. The ambiguity here is figuring out which type of string "csv$" needs to be.
Your solution is to either
turn off OverloadedStrings (if you don't need it for this module), or
add a type annotation to "csv$", so you have \x -> x =~ ("csv$" :: String) instead of \x -> x =~ "csv$" :: Bool
If this is a problem that is cropping up a lot, you may want to play with the ExtendedDefaultRules and have a default declaration in your file.
The reason this succeeds in GHCi is probably because because you didn't have OverloadedStrings enabled there (or possibly due to GHCi's different defaulting rules).

Related

Haskell Wreq - Couldn't match expected type ‘GHC.Exts.Item a0’

I'm experiencing a type error when I run the following code:
runPost :: IO String
runPost = do
res <- post "http://httpbin.org/post" ["num" := (31337 :: Int)]
return $ show res
The error is the following:
• Couldn't match expected type ‘GHC.Exts.Item a0’
with actual type ‘FormParam’
The type variable ‘a0’ is ambiguous
• In the expression: "num" := (31337 :: Int)
In the second argument of ‘post’, namely
‘["num" := (31337 :: Int)]’
In a stmt of a 'do' block:
res <- post "http://httpbin.org/post" ["num" := (31337 :: Int)]
When I inspect the type of := in ghci, I see what appears to be the correct type:
*Main Network.Wreq> :t (:=)
(:=)
:: FormValue v =>
Data.ByteString.Internal.ByteString -> v -> FormParam
What I'm wondering is why GHC.Exts.Item is appearing as the expect type when I run the compiler. I've only imported the functions I'm using from Network.Wreq. Any ideas what might be going on here?
It's clear (to the compiler, if not to your fellow human) that ("num" := (31337 :: Int)) :: FormParam. What isn't clear to the compiler (and which you need to help it decide on) is the type of [x] once x is known to be a FormParam.
The Item "type" is actually a type family, coming from the IsList class; and the IsList connection is coming from having the OverloadedLists extension turned on.
Here's a minimal program that causes basically the same error, which should make it more clear what's going on:
{-# LANGUAGE OverloadedLists #-}
main :: IO ()
main = print [True]
• Couldn't match expected type ‘GHC.Exts.Item a0’
with actual type ‘Bool’
The type variable ‘a0’ is ambiguous
• In the expression: True
In the first argument of ‘print’, namely ‘[True]’
In the expression: print [True]
|
4 | main = print [True]
| ^^^^
The print function has type Show a => a -> IO (). If the OverloadedLists extension weren't enabled, then the expression [True] would have type [Bool], and everything would be fine. But with the OverloadedLists extension enabled, the expression [True] instead has type (GHC.Exts.IsList l, GHC.Exts.Item l ~ Bool) => l. After unifying, print [True] ends up basically having type (Show a, GHC.Exts.IsList a, GHC.Exts.Item a ~ Bool) => IO (). Notice that the type variable a doesn't appear anywhere to the right of the =>, which makes that an ambiguous type. To make the ambiguity even more concrete, note that in addition to [Bool], the type NonEmpty Bool would also work for a there. The compiler doesn't know which one you want and doesn't want to guess, so it gives you that error. To solve the problem, add a type annotation, like this: main = print ([True] :: [Bool])
For the actual problem in your question, the only differences are that you have the Postable typeclass instead of Show, and the FormParam type instead of Bool. You can fix your problem by replacing the erroring line with res <- post "http://httpbin.org/post" (["num" := (31337 :: Int)] :: [FormParam]).

Function length "a" does not compile, if OverloadedStrings extension is enabled

If "{-# LANGUAGE OverloadedStrings #-}" is included at the top of the source file, or in package.yaml (I am using stack), then
length "a" -- does not compile anymore.
However the custom function length' is working fine
length' :: [a] -> Int
length' xs = sum [1 | _ <- xs]
The package Data.String is imported - I think the problem is there, but, I am interested to see, if somebody had similar problem.
Stack and GHC versions:
Version 2.3.1, Git revision x86_64 hpack-0.33.0, ghc-8.8.3
I am using mac osx, but the same error is in Linux and windows too.
This is an error produced by stack:
/Users/admin1/Haskell/PROJECTS/orig1/src/Lib.hs:13:29: error:
• Ambiguous type variables ‘t0’,
‘a0’ arising from the literal ‘"a"’
prevents the constraint ‘(IsString (t0 a0))’ from being solved.
Probable fix: use a type annotation to specify what ‘t0’,
‘a0’ should be.
These potential instances exist:
instance (a ~ Char) => IsString [a] -- Defined in ‘Data.String’
...plus two instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
• In the first argument of ‘length’, namely ‘"a"’
In the first argument of ‘show’, namely ‘(length "a")’
In the second argument of ‘($)’, namely ‘show (length "a")’
|
13 | putStrLn $ show (length "a") -- does not work, if "- OverloadedStrings" is on
This is because length has a signature length :: Foldable f => f a -> Int, so it can be any Foldable type. If you use the OverloadedStrings extension, then "foo" is no longer a String, it can be any type IsString a => a, and multiple fo these can be Foldable f => f as as well.
What you can do is give the compiler a type hint, for example with:
length ("a" :: String)

How can I set up Haskell's GHCI to interactively evaluate functions to their signature (type) instead of getting errors?

To see the function's signature in Haskell GHCI, I have to prefix it with :t:
Prelude> f = \x -> x+1
Prelude> :t f
f :: Num a => a -> a
But typing that prefix every time grows quickly old. If I leave it out, I get error:
Prelude> f
<interactive>:5:1: error:
• No instance for (Show (a0 -> a0)) arising from a use of ‘print’
(maybe you haven't applied a function to enough arguments?)
• In the first argument of ‘print’, namely ‘it’
In a stmt of an interactive GHCi command: print it
Instead of getting this error message, I would like see some useful information about my function f similar to the one I get with :t f (possibly even more information about f).
How can I set up the GHCI to achieve this functionality, i.e. getting function's info upon entering it without :t?
You probably can't do this today. I've opened a feature request to see about adding options to control what GHCi reports about type errors at the prompt.
GHCi will already happily show you the types of anything you type into the prompt, with the option :set +t. The only issue is that show is called on the thing, and there is no proper manner for showing functions - and the type is only printed for an expression which can be shown in a valid manner. However, you can get around this quite easily:
>newtype ShowType a = ShowType a
newtype ShowType a = ShowType a
>instance Show (ShowType a) where show _ = "The type is"
>:set +t
>ShowType const
The type is
it :: ShowType (a -> b -> a)
Unfortunately, this creates quite a lot of syntactic noise. My preferred solution is to add the following to the .ghci file:
:set +t
instance {-# OVERLAPS #-} Show a where show _ = "The type is"
Adding such a Show instance to any real Haskell module would be a grave mistake, but within the .ghci module, it only scopes over expressions typed into the prompt, so it seems okay to me. With this, you get:
>const
The type is
it :: a -> b -> a
>show
The type is
it :: Show a => a -> String
Conveniently, when you have a function whose type is 'technically' valid but has unsatisfiable constraints, you still get a type error:
>:t \x -> x `div` (x / x)
\x -> x `div` (x / x) :: (Integral a, Fractional a) => a -> a
^^^^^^^^^^^^^^^^^^^^^^^^^^
>\x -> x `div` (x / x)
<interactive>:12:1: error:
* Ambiguous type variable `a0' arising from a use of `it'
prevents the constraint `(Fractional a0)' from being solved.
However, the absolute simplest solution is to :set +t and to give a let statement when your expression is non-Showable:
>let _f = show
_f :: Show a => a -> String
Unfortunately, if the left-hand side is the wildcard - let _ = show - then the type is not printed.

RankNTypes with type aliases confusion [duplicate]

This question already has answers here:
Understanding a rank 2 type alias with a class constraint
(2 answers)
Closed 6 years ago.
I'm trying to understand how type constraints work with type aliases. First, let's assume I have next type alias:
type NumList a = Num a => [a]
And I have next function:
addFirst :: a -> NumList a -> NumList
addFirst x (y:_) = x + y
This function fails with next error:
Type.hs:9:13: error:
• No instance for (Num a) arising from a pattern
Possible fix:
add (Num a) to the context of
the type signature for:
addFirst :: a -> NumList a -> a
• In the pattern: y : _
In an equation for ‘addFirst’: ad
Which is obvious. This problem already described here:
Understanding a rank 2 type alias with a class constraint
And I understand why we need {-# LANGUAGE RankNTypes #-} for such type aliases to work and why previous example doesn't work. But what I don't understand is why next example compiles fine (on ghc 8):
prepend :: a -> NumList a -> NumList a
prepend = (:)
Of course it fails in ghci if I try to pass wrong value:
λ: prepend 1 []
[1]
λ: prepend "xx" []
<interactive>:3:1: error:
• No instance for (Num [Char]) arising from a use of ‘prepend’
• When instantiating ‘it’, initially inferred to have
this overly-general type:
NumList [Char]
NB: This instantiation can be caused by the monomorphism restriction.
Seems like type type checking delayed at runtime :(
Moreover, some simple and seems to be the same piece of code doesn't compile:
first :: NumList a -> a
first = head
And produces next error:
Type.hs:12:9: error:
• No instance for (Num a)
Possible fix:
add (Num a) to the context of
the type signature for:
first :: NumList a -> a
• In the expression: head
In an equation for ‘first’: first = head
Can somebody explain what is going on here? I expect some consistency in whether function type checks or not.
Seems like type type checking delayed at runtime :(
Not really. Here it's may be a bit surprising because you get the type error in ghci after having loaded the file. However it can be explained: the file itself is perfectly fine but that does not mean that all the expressions you can build up using the functions defined in it will be well-typed.
Higher-rank polymorphism has nothing to do with it. (+) for instance is defined in the prelude but if you try to evaluate 2 + "argh" in ghci, you'll get a type-error too:
No instance for (Num [Char]) arising from a use of ‘+’
In the expression: 2 + "argh"
In an equation for ‘it’: it = 2 + "argh"
Now, let's see what the problem is with first: it claims that given a NumList a, it can produce an a, no questions asked. But we know how to build NumList a out of thin air! Indeed the Num a constraints means that 0 is an a and makes [0] a perfectly valid NumList a. Which means that if first were accepted then all the types would be inhabited:
first :: NumList a -> a
first = head
elt :: a
elt = first [0]
In particular Void would be too:
argh :: Void
argh = elt
Argh indeed!

Ambiguous type variable `p0' in the constraints

I get the error
Ambiguous type variable `p0' in the constraints:
(Show p0) arising from a use of `print' at cwqr_0003.hs:31:6-10
(Ord p0) arising from a use of `PSQ.lookup'
from the code below.
I have no idea how to analyze this. Could this be a problem in GHC or in one of the modules?
If I try putStr in place of print then I get an error related to the expected type being a string rather then maybe p0. When I try fromMaybe it gives me an error related to the default value literal zero that I send to fromMaybe
import qualified Data.PSQueue as PSQ
import Data.Maybe
import Data.Label
import Control.Category
import Prelude hiding ((.))
--some tested code omitted here
let r = PSQ.lookup test' q
--putStr (show (r :: String))
print (r)
The error message actually means exactly what it says: You have an ambiguous type. How does that happen? Usually, because you have something that produces a polymorphic result, then apply a function that takes a polymorphic argument to that result, such that the intermediate value's type is unknown.
In simple polymorphic types, the ambiguity doesn't matter: If you produce a list of something, then take the length, we don't need to know what the type of the list elements is.
If the ambiguity involves using a type class such as Show, however--which print does--GHC is stuck, because it has no way to know what instance it should pick.
Sometimes this can also arise because a particular definition is forced to be monomorphic (unless you specifically say otherwise), which forces a single type to be chosen instead of retaining the polymorphism. I suspect that might be your problem, but I can't tell without the context you've removed.
To illustrate the latter, the following definition:
foo = print
...with no type signature, causes an error like this:
Test.hs:12:7:
Ambiguous type variable `a0' in the constraint:
(Show a0) arising from a use of `print'
Possible cause: the monomorphism restriction applied to the following:
foo :: a0 -> IO () (bound at Test.hs:12:1)
Probable fix: give these definition(s) an explicit type signature
or use -XNoMonomorphismRestriction
In the expression: print
In an equation for `foo': foo = print

Resources