How to avoid print-related defaulting warning in GHCi - haskell

This code is for an exercise in a textbook.
If I define
minmax :: (Ord a, Show a) => [a] -> Maybe (a, a)
minmax [] = Nothing
minmax [x] = Just (x, x)
minmax (x:xs) = Just ( if x < xs_min then x else xs_min
, if x > xs_max then x else xs_max
) where Just (xs_min, xs_max) = minmax xs
...then, in ghci I get warnings like these:
*...> minmax [3, 1, 4, 1, 5, 9, 2, 6]
<interactive>:83:1: Warning:
Defaulting the following constraint(s) to type ‘Integer’
(Num a0) arising from a use of ‘it’ at <interactive>:83:1-31
(Ord a0) arising from a use of ‘it’ at <interactive>:83:1-31
(Show a0) arising from a use of ‘print’ at <interactive>:83:1-31
In the first argument of ‘print’, namely ‘it’
In a stmt of an interactive GHCi command: print it
Just (1,9)
I had expected that having Show a in the context for minmax's type signature would have eliminated such warnings. I don't understand why this is not enough.
What else must I do to eliminate such warnings? (I'm particularly interested in solutions that do not require defining a new type expressly for the value returned by minmax.)

Numeric literals have polymorphic types, and so do lists of them:
GHCi> :t 3
3 :: Num t => t
GHCi> :t [3, 1, 4, 1, 5, 9, 2, 6]
[3, 1, 4, 1, 5, 9, 2, 6] :: Num t => [t]
To get rid of the warnings, specify the type of the list (or of its elements, which boils down to the same thing). That way, there will be no need for defaulting:
GHCi> minmax ([3, 1, 4, 1, 5, 9, 2, 6] :: [Integer])
Just (1,9)
GHCi> minmax [3 :: Integer, 1, 4, 1, 5, 9, 2, 6]
Just (1,9)
See also Exponents defaulting to Integer for related suggestions involving a slightly different scenario.

Related

How can I make a histogram from a list of integers in Haskell? [duplicate]

This question already has an answer here:
How can I compute a histogram in Haskell?
(1 answer)
Closed 2 years ago.
I'm a Haskell beginner. What's the easiest way of making a histogram from a list of integers? Say I have a list like this:
l = [1, 2, 3, 5, 7, 7, 7, 10]
I'd want to be able to histogram 2 l (for 2 bins) and have it return:
[(0, 3), (1, 5)]
Since there are three numbers in the 0th (first) half, and five numbers in the other half.
There are a lot of libraries that seem to do this, but marshalling a list of integers to and from Vectors or other data structures is really confusing me.
Here's one thing I've tried:
import Statistics.Sample.Histogram
l = [1, 2, 3, 5, 6, 7, 7, 7, 7] :: [Double]
main = print $ snd $ histogram 10 l
But the error it throws is:
histogram-test.hs:6:8: error:
• Ambiguous type variables ‘v10’,
‘b0’ arising from a use of ‘print’
prevents the constraint ‘(Show (v10 b0))’ from being solved.
Probable fix: use a type annotation to specify what ‘v10’,
‘b0’ should be.
These potential instances exist:
instance Show a => Show (Maybe a) -- Defined in ‘GHC.Show’
instance (Show a, Show b) => Show (a, b) -- Defined in ‘GHC.Show’
instance (Show a, Show b, Show c) => Show (a, b, c)
-- Defined in ‘GHC.Show’
...plus 13 others
...plus 19 instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
• In the expression: print $ snd $ histogram 10 l
In an equation for ‘main’: main = print $ snd $ histogram 10 l
|
6 | main = print $ snd $ histogram 10 l
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
histogram-test.hs:6:22: error:
• No instance for (Data.Vector.Generic.Base.Vector [] Double)
arising from a use of ‘histogram’
• In the second argument of ‘($)’, namely ‘histogram 10 l’
In the second argument of ‘($)’, namely ‘snd $ histogram 10 l’
In the expression: print $ snd $ histogram 10 l
|
6 | main = print $ snd $ histogram 10 l
| ^^^^^^^^^^^^^^
Failed, no modules loaded.
I think you have to be forcefully explicit with the data types you expect to get.
$ ghci
GHCi, version 8.6.5: http://www.haskell.org/ghc/ :? for help
...
λ>
λ> import qualified Data.Vector as V
λ> import Statistics.Sample.Histogram
λ>
λ> l = [1, 2, 3, 5, 6, 7, 7, 7, 7] :: [Double]
λ> hi = (histogram 10 (V.fromList l)) :: (V.Vector Double, V.Vector Int)
λ>
λ> part2 = snd hi
λ>
λ> part2
[1,1,0,1,0,0,1,1,0,4]
λ>
Also, it could be that the statistics folks are overwhelmingly of the Fortran/C/C++ culture, and consequently they regard Haskell lists as nice stuff for computer scientists; however, when doing statistics, lists are expected to be converted into some serious data type, like sequence or vector.
What this error line:
No instance for (Data.Vector.Generic.Base.Vector [] Double)
means to tell us is that a list cannot make a proper vector, that is a proper food for function histogram. You have to allow explicitely the compiler to convert from list to vector.
It is quite easy to implement this yourself without relying on any library (other than containers, to provide a Map type for the result):
frequencies :: Ord a => [a] -> M.Map a Int
frequencies = foldr (\x m -> M.insertWith (+) x 1 m) M.empty

Trying to understand zip

I am attempting to understand how to use zip in Haskell. I've been learning Haskell recently and am trying to create a list of tuples from two separate lists
I have the following:
createList :: [Char] -> [Char] -> [(Char,Char)]
createList xs ys = zip(xs,ys)
I understand zip is supposed to create a list of tuples given two lists, but I get the following error:
Couldn't match expected type ‘[a0]’
with actual type ‘([Char], [Char])’
Can anyone explain to me where I am stumbling?
Haskell function calls don't use brackets or commas.
You can write the createList function as:
createList xs ys = zip xs ys
or simply
createList = zip
Thus, the createList function is redundant; it's just zip. The only potential use for the alias that I can think of is if you truly want to constrain the type as given.
If you remove the parenthesis around zip call, your code should work:
createList :: [Char] -> [Char] -> [(Char,Char)]
createList xs ys = zip xs ys
Explanation:
Full error I am getting when I run zip ([1, 2, 3], [4, 5, 6]) (notice the parens):
<interactive>:4:5:
Couldn't match expected type ‘[a]’
with actual type ‘([Integer], [Integer])’
Relevant bindings include
it :: [b] -> [(a, b)] (bound at <interactive>:4:1)
In the first argument of ‘zip’, namely ‘([1, 2, 3], [4, 5, 6])’
In the expression: zip ([1, 2, 3], [4, 5, 6])
In an equation for ‘it’: it = zip ([1, 2, 3], [4, 5, 6])
Notice the part that says In the first argument of ‘zip’, namely ‘([1, 2, 3], [4, 5, 6])’. The parens are interpreted as tuple constructor. zip function expects a list as its first argument but we are passing it a tuple.

map the min command to a multilevel list in haskell

I want to find the smallest values in a set of lists
map min [[1, 3], [2, 7],[9, 6]]
I would like this to output
[[1],[2],[6]]
It gives the error:
* No instance for (Show ([Integer] -> [Integer]))
arising from a use of `print'
(maybe you haven't applied a function to enough arguments?)
* In a stmt of an interactive GHCi command: print it
min :: Ord a => a -> a -> a works on two items to return the minimum of the two. You are probably looking for minimum :: (Foldable f, Ord a) => f a -> a instead:
Prelude> map minimum [[1, 3], [2, 7],[9, 6]]
[1,2,6]
Here the items are not wrapped in individual sublists, but that would only result in an (unnecessary) extra layer of indirection.

Simple print in haskell script: how to write main function?

I am starting to learn haskell, but cannot find a way to have a working main function. I have already made it work somehow, but I think it was pure luck because I cannot get it again.
Basically, what I want to do is create a script file to be run like runhaskell script.hs from terminal.
So the basic structure would be the function declaration followed by a main = do or something, and the function being called to print its result.
For example, I took this from "Learn you a Haskell", but the following code doesn't work:
elem' :: (Eq a) => a -> [a] -> Bool
elem' y ys = foldl (\acc x -> if x == y then True else acc) False ys
main :: IO()
main = print (elem' 1 [1,2,3,4])
This gives me the error:
Build FAILED
/home/helton/Desktop/apaga.hs: line 6, column 16:
Warning: Defaulting the following constraint(s) to type `Integer'
(Eq a0)
arising from a use of elem'
at /home/helton/Desktop/apaga.hs:6:16-20
(Num a0)
arising from the literal `1' at /home/helton/Desktop/apaga.hs:6:22
In the first argument of `print', namely `(elem' 1 [1, 2, 3, 4])'
In a stmt of a 'do' block: print (elem' 1 [1, 2, 3, 4])
In the expression: do { print (elem' 1 [1, 2, 3, 4]) }
print (elem' 1 [1,2,3,4])
While I expected something like
> True
Try replacing
print (elem' 1 [1, 2, 3, 4])
with
print (elem' (1::Int) [1, 2, 3, 4])
The issue here is that Haskell can't determine whether your numeric literals should be interpreted as Ints or Doubles or any other numeric type.
Specifying the type for any numeric literal here is enough, since elem' requires all of them to be of the same type, hence once the type of any one of them is known such type can be used for everything else.

Avoid warning Defaulting the following constraint(s) to type `Integer'

I have defined the following function to reverse a list of Int or string:
myReverse :: [a] -> [a]
myReverse [] = []
myReverse (x:xs) = (myReverse xs) ++ [x]
My test with hspec:
describe "myReverse" $ do
it "returns the inversed list of the given list" $ do
myReverse [1,2,3,4] `shouldBe` [4,3,2,1]
it "returns the inversed string of the given string" $ do
myReverse "A man, a plan, a canal, panama!" `shouldBe` "!amanap ,lanac a ,nalp a ,nam A"
Like this I get the warning
tests/OneToTenSpec.hs:69:24:
Warning: Defaulting the following constraint(s) to type `Integer'
(Eq a0)
arising from a use of `shouldBe' at tests/OneToTenSpec.hs:69:24-33
(Num a0)
arising from the literal `1' at tests/OneToTenSpec.hs:69:15
(Show a0)
arising from a use of `shouldBe' at tests/OneToTenSpec.hs:69:24-33
In a stmt of a 'do' block:
myReverse [1, 2, 3, 4] `shouldBe` [4, 3, 2, 1]
In the second argument of `($)', namely
`do { myReverse [1, 2, ....] `shouldBe` [4, 3, ....] }'
In a stmt of a 'do' block:
it "returns the inversed list of the given list"
$ do { myReverse [1, 2, ....] `shouldBe` [4, 3, ....] }
So I made the following change on the test
myReverse [1 :: Int,2,3,4] `shouldBe` [4,3,2,1]
Is there is another way to avoid this warning than defining the type of an element of the list ?
Not with numeric literals. Since literals have the type Num a => a and we're feeding it to a function that's polymorphic in a, there are no hints as to what to resolve a to.
The good news is that this is exactly how defaulting is meant to work and you have nothing to worry about! The warning is annoying though, I can think of two ways to avoid it
Use explicit type signatures
Don't use numeric literals
2 will probably be the best in your scenario, we know from the type that the type of element can't impact its function, so you're free to use Bool
myReverse [True, False] `shouldBe` [False, True]
As an aside your current implementation is O(n^2) and O(n) is possible, I'll leave it to you to figure out how though :)

Resources