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

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)

Related

How does GADTs affect type inference in this case?

Say I have a monad that emits soft failure through Writer. A simplified version goes like this (for the record, I'm using GHC 9.0.2):
{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE FlexibleContexts #-}
-- {-# LANGUAGE GADTs #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Lib where
import Control.Monad.Writer.CPS
import Data.Maybe
verify :: MonadWriter [String] m => some -> args -> m ()
verify _ _ = fix \(_ :: m ()) ->
do
let warn = tell . (: [])
a = Just 1 :: Maybe Int
b = Just [1, 23] :: Maybe [Int]
c = Just (id :: forall a. a -> a)
-- isJust' :: String -> Maybe a -> m ()
isJust' tag v = unless (isJust v) do
warn $ tag <> " is Nothing"
isJust' "a" a
isJust' "b" b
isJust' "c" c
All goes fine until I add GADTs extension, then GHC fails to find the most general type for isJust':
• Couldn't match type ‘[Int]’ with ‘Int’
Expected: Maybe Int
Actual: Maybe [Int]
• In the second argument of ‘isJust'’, namely ‘b’
In a stmt of a 'do' block: isJust' "b" b
In the expression:
do let warn = tell . (: [])
a = ...
....
isJust' "a" a
isJust' "b" b
isJust' "c" c
|
22 | isJust' "b" b
| ^
/var/tmp/demo/src/Lib.hs:23:17: error:
• Couldn't match type ‘a0 -> a0’ with ‘Int’
Expected: Maybe Int
Actual: Maybe (a0 -> a0)
• In the second argument of ‘isJust'’, namely ‘c’
In a stmt of a 'do' block: isJust' "c" c
In the expression:
do let warn = tell . (: [])
a = ...
....
isJust' "a" a
isJust' "b" b
isJust' "c" c
|
23 | isJust' "c" c
| ^
At which point I have to uncomment type annotation for isJust' to get this to type check - I'm wondering what is at play here, I don't think I'm using any GADTs features?
Side note 1: I usually just slam a NoMonomorphismRestriction to see if it helps, it didn't.
Side note 2: That use of fix is just for getting a hold on that m in the presence of ScopedTypeVariables - a side question is whether there are better ways to do this without relying on verify having an explicit type signature (say this function is defined inside an instance).
The problem is not GADTs but MonoLocalBinds, which is automatically enabled by GADTs. The issue is that isJust' :: String -> Maybe a -> m () has a polymorphic type signature, meaning you get to choose what a is every time you call it. At least, it would be polymorphic if MonoLocalBinds wasn't enabled. Per the documentation:
With MonoLocalBinds, a binding group will be generalised if and only if
It is a top-level binding group, or
Each of its free variables (excluding the variables bound by the group itself) is closed (see next bullet), or
Any of its binders has a partial type signature (see Partial Type Signatures).
If a variable does not satisfy one of the three bullets, its type is not generalized, i.e. it does not get to be polymorphic.
There is a rigorous definition of what a "closed variable" is, but the important part is:
if a variable is closed, then its type definitely has no free type variables.
The second argument of isJust' has type Maybe a for some unknown a, meaning it is not closed (edit: see Li-yao Xia's correction in the comments). So, bullet 1 is not satisfied because isJust' is defined within verify, bullet 2 is not satisfied because the second argument of isJust' is not closed, and bullet 3 is not satisfied because there are no holes in the type of isJust'. Thus, isJust' is not polymorphic after all.
All this means is that the a in String -> Maybe a -> m () is actually a fixed type that GHC has to infer. It sees you call isJust' "a" (a::Maybe Int) and assumes a ~ Int, but then it sees isJust' "b" (b::Maybe [Int]) and assumes a ~ [Int] as well. Obviously this is a problem, so GHC complains. The only thing adding the type signature does is tell GHC to make isJust' polymorphic.
Note that you can have GADTs and NoMonoLocalBinds at the same time, but because type inference with GADTs is tricky this will probably just cause more problems when you actually use GADTs.

Testing empty list [] with Eq type

Currently, I am writing a function in Haskell to check a list is symmetric or not.
isReflexive :: Eq a => [(a, a)] -> Bool
isReflexive [] = True
isReflexive xs = and [elem (x, x) xs | x <- [fst u | u <- xs] ++ [snd u | u <- xs]]
test = do
print(isReflexive [])
main = test
The function works fine on the list that is not empty. However, when I test the empty list with the function, it raised an error
Ambiguous type variable ‘a2’ arising from a use of ‘isReflexive’ prevents the constraint ‘(Eq a2)’ from being solved.
Probable fix: use a type annotation to specify what ‘a2’ should be.
These potential instances exist:
instance Eq Ordering -- Defined in ‘GHC.Classes’
instance Eq Integer -- Defined in ‘integer-gmp-1.0.2.0:GHC.Integer.Type’
instance Eq a => Eq (Maybe a) -- Defined in ‘GHC.Maybe’
...plus 22 others
...plus 7 instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
• In the first argument of ‘print’, namely ‘(isReflexive [])’
How to fix this error?
The problem is simply that, in order to apply isReflexive, GHC needs to know which type you are using it on.
The type signature of isReflexive - Eq a => [(a, a)] -> Bool doesn't tell GHC a concrete type that the function works on. That's perfectly fine, and usual, but most often the code that calls the function makes it clear what exactly a is in that particular application. That's not so here, because [] has itself a polymorphic (and therefore ambiguous) type, [a] (for any a).
To fix it you simply have to provide a concrete type for your [] here, which is consistent with the signature of isReflexive. It really doesn't matter what, but an example from many that will work is:
test = do
print(isReflexive ([] :: [(Int, Int)]))
(Note that this is exactly what GHC is telling you when it says Probable fix: use a type annotation to specify what 'a2' should be. 'a2' in that message corresponds to 'a' here, GHC tends to use 'a1', 'a2' etc to refer to all type variables.)

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

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).

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!

Resources