- [[Char]] : Not sure if writing this is right or not, and not sure if it really means a list of strings.
Yes, it does mean a list of strings - that is, the type [String]
. This is the same as [[Char]]
because in Haskell String
and [Char]
are type synonyms, literally different ways of referring to the exact same thing. So putting a pair of square brackets round each (to denote a list of that type) also leads to two equivalent types.
String
is usually considered more idiomatic than [Char]
when writing Haskell code, but it's not a big deal. (Even if you use String
everywhere, the compiler might still use [Char]
when reporting errors, so it's important to know about this equivalence.)
- orderedCheck $ fst b : this is the part where I have a GHC error : "No instance for (Ord a) arising from a use of ‘orderedCheck’ ",I looked around and I can't understand what does it mean.
It's exactly as @Ismor said in the comments - but as I have a little more space in an answer I'll try to give a slightly longer, clearer explanation.
You are calling orderedCheck
with the value fst b
. And orderedCheck
, by your own (correct) type signature, has type (Ord a) => [a] -> Bool
. That means its argument must be a list, whose elements are of a type a
which satisfies the constraint Ord a
.
But you are using it on fst b
in testReturn
. b
is the second argument to the function, which from its type signature must be of type ([a], [b])
. This means fst b
must be of type [a]
- which is a list, so so far so good. But as just mentioned, that type a
must have an instance of Ord
. And unfortunately we can't guarantee that, because your type signature - [[Char]] -> ([a], [b]) -> Bool
- allows both a
and b
to be absolutely anything. If this code compiled, that type signature would allow me to call that function as, for example, testReturn ["Example"] ([putStrLn "foo"], [])
- but putStrLn "foo"
has type IO ()
, which certainly has no Ord
instance. (Unless you provide one in your code, which doesn't sound like a great idea - but even if you did, you could easily find another type with no Ord
instance which would lead to the same problem.)
The only way to fix this is to fix the type signature of testReturn
- it can't actually accept any type as a
, because that type must have an Ord
instance. So include that requirement, and you'll be fine:
testReturn :: (Ord a) => [[Char]] -> ([a], [b]) -> Bool
(As @MarkSeemann notes, that's exactly the signature GHC would have inferred for you if you'd left out any type signature. I certainly don't recommend leaving off type signatures for top-level functions, but if you're ever not sure of what the signature should be, this technique of leaving it out and then asking GHCi to infer it for you with :t
is almost guaranteed to give you what you want.)
- I heard somewhere else that the use of fst and snd may be a bit edgy (is it?), but I don't know how to do without it.
I'm not sure what "edgy" means in this context. It's certainly not "wrong", nor is it dangerous in the same way that head
and tail
are for lists - those functions will crash (at runtime) when given an empty list, whereas fst
and snd
will work fine for any 2-tuple (and if given a value that's not a 2-tuple, your code will fail to compile - so there is zero risk of a runtime crash).
However, it's not very elegant compared to pattern-matching, which here is rather like "destructuring" in other languages. I think most Haskellers would write your function like this instead, which is equivalent to your code and hopefully self-explanatory:
testReturn [] (b, _) = orderedCheck b
testReturn (a:as) (b, c)
| a == "sa" = testReturn as (saFunc b, c)
(Note that this function appears incomplete, and will crash if called with a non-empty first argument whose first element is anything other than "sa"
.)
a
intestReturn
has no restrictions, but it usesorderedCheck
which imposeOrd a
, hence the error – lsmortestReturn
and use GHCi's:type
command to ask it about the inferred type. – Mark Seemann