Why is GHC complaining about wrong type? - haskell

This little function checks a (finite) Brainfuck string for validity. It check's whether the [ and ] are balanced. The code is very straightforward and written to be tail-recursive:
-- checks Brainfuck for validity.
validateBrainfuck :: Monad m => String -> m String
validateBrainfuck s = maybe (return s) (fail . fromJust) (validate s 0) where
validate :: String -> Int -> Maybe String -- Here inversed: String means error
validate (']':_ ) 0 = Just "Too many closing brackets"
validate (']':xs) c = validate xs (pred c)
validate ('[':xs) c = validate xs (succ c)
validate ( x :xs) c = validate xs c
validate [] 0 = Nothing
validate [] _ = Just "Too many opening brackets"
Now, GHC complains about typing issues:
Brainfuck.hs:62:58:
Couldn't match expected type `Maybe String'
against inferred type `[Char]'
Expected type: Maybe (Maybe String)
Inferred type: Maybe String
In the third argument of `maybe', namely `(validate s 0)'
In the expression:
maybe (return s) (fail . fromJust) (validate s 0)
Maybe I'm just too silly to figure out what went wrong, but this looks very weird for me.

Look at the type of maybe and think what it should do:
maybe :: b -> (a -> b) -> Maybe a -> b
If the maybe value contains no result (i.e. Nothing), maybe returns the b argument.
Otherwise - when Just a is given - it applies the given function to the valid result. We don't need any fromJust extraction here.
Your code just becomes
maybe (return s) fail (validate s 0)

Related

How to get value from Either?

I have this code in ghci,try to decode base64 code:
let a=pack "MTExMTEx"
let b=decode a
:t b
b :: Either String ByteString
so how to get the decode bytestring from either?is there some func like Maybe's fromJust?I can't find it,thanks.
Use case:
case decode a of
Left err -> {- what to do if decode gave an error -}
Right msg -> {- what to do if decode succeeded -}
The either function that Alexandre suggests is essentially the same as this, the two branches are just taken as functions instead; i.e. it's equivalent to write:
either
(\err -> {- what to do if decode gave an error -})
(\msg -> {- what to do if decode succeeded -})
(decode a)
You can use the either function from Data.Either.
Its signature is:
either :: (a -> c) -> (b -> c) -> Either a b -> c
It means it takes two functions as inputs: the first one to be applied in case it's a Left, and the second one to be applied if it's a Right. The third parameter is your Either data type. Notice that the type of the return value of both functions must be the same.
You're looking for Data.Either's fromRight which has a type signature
fromRight :: b -> Either a b -> b
the first value is a default value (what you'll get back if you have a Left instead of a Right.
fromRight 'a' (Left "b")
-- gives 'a'
fromRight 'a' (Right 'c')
-- gives 'c'

Check if a string contains a certain character

I need to check if my string contain a specific character.
I tried this:
charFound :: Char -> String -> Bool
charFound c s = filter(\x -> x == c) s
But it gives me:
Couldn't match expected type Bool with actual type [Char]
I know that filter:
returns a list constructed from members of a list (the second argument) fulfilling a condition given by the first argument.
How could I reach the goal and return a bool instead of a list?
For your purpose, you could use the function elem :: Eq a => a -> [a] -> Bool from prelude. It does exactly what it says on the label. To implement this function, I would use something like this:
elem = any . (==)
or even more elementary:
elem x = foldr ((||) . (x ==)) False
Notice that due to the short-circuit behaviour of (||) this also works with infinite lists as long as x is found.
The type of filter is (a -> Bool) -> [a] -> [a].
You have supplied the first argument which has type Char -> Bool (which is correct), then the second argument which is String (that's [Char]) which is correct, so the type of filter (\x -> x == c) s is [Char].
But the type signature you have provided says the function returns a Bool, which doesn't match the actual type returned.
You probably want to use any instead of filter. It's type is (a -> Bool) -> [a] -> Bool.
There's also an all function that returns True if and only if all elements of the list satisfy the predicate passed. You may also consider the functions or and and that given a [Bool] compute the disjunction or conjunction of the values. So any f = or . map f and all f = and . map f.
For all list-related functions see the Data.List module.

Infinite Square Roots : Couldn't match expected type & cannot construct the infinite type

Sorry for what's probably an idiot question - trying to learn Haskell at the moment;
I'm trying to build a basic function that will create an infinite list of square roots on a number, so I can get practice with the take function and how it works.
I wrote the following code;
infisqrt x = infisqrt'((x :: Float) [])
-- helper method
infisqrt' x xs = infisqrt'(sqrt(x) (xs ++ [(sqrt(x))]))
However, this is returning with two errors when trying to load the library;
:l isq
isq.hs:1:24:
Couldn't match expected type ‘[t0] -> a’ with actual type ‘Float’
Relevant bindings include
infisqrt :: Float -> [a] -> t (bound at isq.hs:1:1)
The function ‘x :: Float’ is applied to one argument,
but its type ‘Float’ has none
In the first argument of ‘infisqrt'’, namely ‘((x :: Float) [])’
In the expression: infisqrt' ((x :: Float) [])
isq.hs:5:33:
Occurs check: cannot construct the infinite type: a ~ [a] -> a
Relevant bindings include
xs :: [a] (bound at isq.hs:5:13)
x :: a (bound at isq.hs:5:11)
infisqrt' :: a -> [a] -> t (bound at isq.hs:5:1)
In the first argument of ‘sqrt’, namely ‘(x)’
In the first argument of ‘infisqrt'’, namely
‘(sqrt (x) (xs ++ [(sqrt (x))]))’
Can anyone let me know where I'm going wrong with this?
Haskell function invocation doesn't use parentheses. It looks like you're expecting this:
infisqrt x = infisqrt'((x :: Float) [])
to mean "pass x and [] as arguments to inifsqrt." However, to the compiler, it actually means "pass [] as the first argument to x, and then pass the result to infisqrt'." If you take the extra parentheses out, you should start getting traction:
infisqrt x = infisqrt' (x :: Float) []
(remember, you've got the same thing going on in infisqrt''s definition)
As a side note, it's typically preferable to put arguments' types in a function type declaration:
infisqrt :: Float -> [Float]
infisqrt x = infisqrt' x []

Cannot Deduce (simple) Typeclass from context

I'm getting an error in a pretty simple example and I'm unable to figure out what is wrong. What I'm doing is very similar to mempty in Monoid, here is a simple version (I include my quantified type in case that has something to do with the issue):
data Field a = Field String
| forall b. EsMappable b => ReferenceField String (a -> b)
class EsMappable a where
fields :: [Field a]
toMapping :: (EsMappable a) => a -> String
toMapping a = go "" fields
where go str [] = str
go str (ReferenceField name _ : xs) = go (name ++ str) xs
go str (Field name : xs) =go (name ++ str) xs
The error I get is:
Could not deduce (EsMappable t0) arising from a use of ‘fields’
from the context (EsMappable a)
bound by the type signature for
toMapping :: EsMappable a => a -> String
at search2.hs:11:14-42
The type variable ‘t0’ is ambiguous
In the second argument of ‘go’, namely ‘fields’
In the expression: go "" fields
In an equation for ‘toMapping’:
toMapping a
= go "" fields
where
go str [] = str
go str (ReferenceField name _ : xs) = go (name ++ str) xs
go str (Field name : xs) = go (name ++ str) xs
Note: if I change the EsMapapble class to: fields :: a -> [Field a] and then in toMapping I change go "" (fields a), it works.
My Question: why am I getting this error? Is this not the same as mempty? What is preventing GHC from properly resolving fields?
Thank you!
The problem is that the compiler has no way to link your use of fields to your argument a. Your go function can take in a [Field a] for any a, so you need to somehow specifically constrain it to be the same as the a in your argument type.
You can do this nicely with ScopedTypeVariables:
toMapping :: forall a. (EsMappable a) => a -> String
toMapping _ = go "" (fields :: [Field a])
You need the extra forall a to explicitly make the a type variable scoped. This is a restriction on ScopedTypeVariables in the interest of backwards compatibility.
This would also not have been a problem if you had used your a argument with the Field a values in go. As a contrived example, the following typechecks without the explicit signature:
go str (ReferenceField name f : xs) = go (name ++ str) xs `const` f a
This forces f to take an argument of type a, which constrains the whole list to that specific a. So you could actually use this trick to avoid the ScopedTypeVariables extension if you really wanted to! I wouldn't suggest that though: the extension is about as harmless as they come and makes the code much clearer. This example was just for illustrating my point.

Haskell data type error

I have this function:
data Memory = Memory
{visited::[Point]
,dfsstack::[Point]
,currentPoz::Point
}deriving(Eq)
perceiveAndAct :: SVal -> [Cardinal] -> a -> (Action, a)
perceiveAndAct s cs m
| elem W cs == True && elem N cs == True && elem E cs == True && elem S cs == False = (Just S, Memory (visited m) (dfsstack m) (currentPoz m))
putting m instead of Memory (visited m) (dfsstack m) (currentPoz m) works fine, else it gives me that:
Couldn't match expected type `(a, b)'
against inferred type `Memory -> Point'
In the first argument of `fst', namely `currentPoz'
In the first argument of `($)', namely `fst currentPoz'
In the expression: fst currentPoz $ currentPoz m
What could be the problem?
The type you gave perceiveAndAct is very polymorphic. Compare:
id :: a -> a
id m = m -- the only correct implementation
id m = Memory (visited m) (dfsstack m) (currentPoz m) -- type error
-- only works for Memory, not all possible a
idMemory :: Memory -> Memory
id m = m -- this is fine
id m = Memory (visited m) (dfsstack m) (currentPoz m) -- also correct
However, I'm a little confused, since the type error you pasted does not match the type error I get when I make the change you claimed you made. Perhaps you'd better paste the exact code you use that gives an error together with the exact error you got, rather than the correct code and the error for some invisible code we can't see.
visited, dfsstack, and currentPoz are functions, and they don't construct lists.
You want to write Memory [m] [m] m, instead.
visited, dfsstack, and currentPoz are functions which, given someData :: Memory, can extract each of these elements.
You'll also need to change the type of perceiveAndAct's argument "m" from :: a to :: Point

Resources