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

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.

Related

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.

How to avoid print-related defaulting warning in GHCi

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.

First Haskell program

i write a little code in Haskell to learn haskell. It looks like:
first :: [Int] -> Int -> Int
first [] x = x
first xs y = y
I wanted to express that i get a list([] or xs) and an argument(x or y) and no matter how the lists look like, the argument should presented.
So, when I write the following: first [1,2,3] 4, then ghci says:
Couldnt match expected type ´a0 -> t´ wth actual type ´[t0]´. Relevant bindings
include it :: t(boudn at <>:6:1)but its type ´[t 0]´ has none
In the expression : [1,2,3] 4
In an equation for ´it´: it = [1,2,3] 4
How can i fix it? What mistakes i´ve made? Can someone help me?
It looks like you use [1,2,3,4] 4 instead of first [1,2,3,4] 4.
> [1,2,3,4] 4
<interactive>:1:0:
Couldn't match expected type `t1 -> t' against inferred type `[a]'
In the expression: [1, 2, 3, 4] 4
In the definition of `it': it = [1, 2, 3, 4] 4
By the way, your definition of first is the same as the following:
first :: [Int] -> Int -> Int
first _ x = x
which means no matter what the first argument is, always returns the second argument.

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

Haskell beginner order function

My code:
isOrdered :: (a -> a -> Bool) -> [a] -> Bool
isOrdered mark xs =(head xs) `mark`(head(tail xs))
Compiles perfectly but when I try to call it with
isOrdered < [1,2,3]
I get an error:
Couldn't match expected type `(a0 -> a0 -> Bool) -> [a0] -> Bool'
with actual type `[t0]'
In the second argument of `(<)', namely `[1, 2, 3]'
In the expression: isOrdered < [1, 2, 3]
In an equation for `it': it = isOrdered < [1, 2, 3]
What am I missing here?
Since < is infix, you have to wrap it in parens. This converts it to be prefixed.
1 < 2 ==> (<) 1 2
1 + 5 ==> (+) 1 5
Then you're code becomes
isOrdered (<) [1, 2, 3]
This is actually part of a more general concept of sectioning. You can completely convert an infix operator to prefix with parens, or partially apply it like this
\x -> x + 1 ===> (+1)
\x -> 2 ^ x ===> (2^)
The only place where this goes a bit pear-shaped is with -. Since - is a super special prefix operator defined by the Haskell language, you can't do (-2), since it's not clear whether this is a section or a number. Haskell chooses a number, but if you want a section, there is a function subtract.
\x -> x - 2 ==> subtract 2
This works:
isOrdered (<) [1,2,3]
Not sure why, though. It’s a general thing:
Prelude> :type <
<interactive>:1:1: parse error on input `<'
Prelude> :type (<)
(<) :: Ord a => a -> a -> Bool
I’m sure others will explain.
When passing an operator to a higher level function, you have to surround it with parentheses:
isOrdered (<) [1, 2, 3]
You also have to do this for partially applied operators
map (== 2) [1, 2, 3]
This is not an answer to your question, but just a stylistic tip: idiomatic Haskell code should use pattern matching instead of head/tail. Pattern matching statically ensures that you don't accidentally try to access inexistent elements.
The way you would write your function using pattern matching is:
isOrdered :: (a -> a -> Bool) -> [a] -> Maybe Bool
isOrdered mark (x:y:_) = Just (x `mark` y)
isOrdered _ _ = Nothing
Note that I've included a case for when the list does not contain two elements and wrapped the result in a Maybe. This prevents run-time errors by forcing you to handle that case.

Resources