Map that associates operators with lambda functions - haskell

I have a Haskell Map, containing strings as keys and some lambda functions as items .
Eg.:
-- List of supported Operators -> mapping with functions
ops = Map.fromList [("+", \x y -> x + y),
("-", \x y -> y - x),
("*", \x y -> x * y),
("/", \x y -> y / x)]
I want to write a function that takes as input:
A string representing an operator ["+", "-", "*", "/"]
Two numbers
Based on the operator and the ops map, the function will evaluate the sum/subtraction/etc. of the two numbers .
I've tried something like:
(Map.lookup "+" a) 1 2
But it's not working .
The error is:
Top level:
No instance for (Show (Integer -> Integer))
arising from use of `print' at Top level
Probable fix: add an instance declaration for (Show (Integer
In a 'do' expression: print it
<interactive>:1:1:
No instance for (Monad ((->) t))
arising from use of `Data.Map.lookup' at <interactive>:1:1-
Probable fix: add an instance declaration for (Monad ((->) t)
In the definition of `it': it = (Data.Map.lookup "+" a) 1 2
... not very helpful for me.
Any suggestions ? Thank you !

lookup is of type lookup :: Ord k => k -> Map k a -> Maybe a. The result is wrapped in a Maybe to indicate that the key may not be present in the map.
Here's a way to do it that will work:
runOp :: String -> a -> a -> b
runOp key x y = case lookup key ops of
Just op -> op x y
Nothing -> error ("Couldn't find operator: " ++ key)
This will bottom out if the key is not present. You could also return an Either or Maybe result from runOp to accommodate the possibility that the key isn't present, but that's up to you.
Maybe is defined as follows:
data Maybe a = Just a | Nothing
that is, it either holds a result value or an empty value. Like an existential philosopher, Haskell forces you to acknowledge the possibility of Nothing.

First of all the error you showed is not caused by the code you showed. Your code causes the following error (in ghc):
Couldn't match expected type `t1 -> t2 -> t'
against inferred type `Data.Maybe.Maybe
That error is caused by the fact that lookup returns a Maybe. So you need to unwrap the Maybe first.

import Control.Applicative
ops :: (Fractional a) => Map.Map String (a -> a -> a)
ops = Map.fromList [("+", (+)),
("-", flip (-)),
("*", (*)),
("/", flip (/))]
apply :: (Fractional a) => String -> a -> a -> Maybe a
apply op x y = Map.lookup op ops <*> y <*> x
Because lookup returns a Maybe a (well, Maybe (a -> a -> a) in this case), there is no way to directly apply it to an a. We can use <*> to pull the LHS out of the mote, apply it to the RHS, and inject it back into the monad. (Or do it manually like Bill.)

Related

Haskell "Non type-variable argument in the constraint"

I've created a list of partially applied functions in my REPL like so:
listOfPartiallyAppliedFunctions = map (*) [1..100]
I would then like to create the list of results from completing the function application, which I can easily do by providing a lambda to the map function like so:
let results = map (\x -> x 4) listOfPartiallyAppliedFunctions
Which basically means map the function x applied to 4 over the list of partially applied functions, where x is each partially applied function from the list.
However, I thought it would then follow that I could write:
let results = map (4) listOfPartiallyAppliedFunctions
As there shouldn't be a need to provide a lambda to the map function as it should know to apply 4 to the partially applied functions contained in the listOfPartiallyAppliedFunctions.
However, I am getting this error:
• Non type-variable argument in the constraint: Num ((a -> a) -> b)
(Use FlexibleContexts to permit this)
• When checking the inferred type
it :: forall a b. (Num a, Num ((a -> a) -> b), Enum a) => [b]
Can someone help me parse this error? I thought 4 was an instance of type constructor Num?
However, I thought it would then follow that I could write:
let results = map (4) listOfPartiallyAppliedFunctions
No, if you would have performed \x -> 4 x, you could replace it with 4. But since 4 means it is a Num instance, and you likely did not make a function a -> b an instance of Num, the compiler can not solve this. The compiler thus says that it does not find a way to convert the number 4 into a function, and definitely not a function that takes as input a function Num a => a -> a, and then converts this to a b.
You can however write the above as just:
let results = map ($ 4) listOfPartiallyAppliedFunctions
Here we thus perform a sectioning of an infix operator [Haskell-wiki] on the ($) :: (a -> b) -> a -> b function.
Three "laws" of operator sections are
(a `op` b) = (a `op`) b = (`op` b) a = op a b
(the missing argument goes into the free slot near the operator),
or with $,
a b = (a $ b) = (a $) b = ($ b) a = ($) a b
Thus
(\ x -> x 4) = (\ x -> x $ 4) = (\ x -> ($ 4) x)
and that, by eta-reduction, is
($ 4)

Haskell foldl and foldl1 produce "No instance for (Num [Char]) arising from the literal"

I think these two fold functions are the same, but only the second one works. The first one produce No instance for (Num [Char]) arising from the literal ‘12’ error. Why does the first one produce this error?
foldl1 (\x y -> (show x) ++ (show y)) [12,23,45,66]
foldl (\x y -> x ++ (show y)) "" [12,23,45,66]
Thank you
Look closely at the type:
foldl1 :: Foldable t => (a -> a -> a) -> t a -> a
The values need to be converted to [Char] before the function is called, because the function expects its arguments' type and the return type to be the same. (And only the first use of the function gets two arguments of the same type.)
To use foldl1, map show over the list first.
foldl1 (++) (map show [12, 23, 45, 66])
If you look at the type signature for foldl1 :: Foldable t => (a -> a -> a) -> t a -> a, you'll see that the lambda has to return the same type as the one in the list. This is because that returned value is then used to compute the next step.
This does not occur in foldl because the lambda can return any type as that value is only used as an accumulator. I don't have time to write a more clear answer but just google foldl1 to understand the difference

Couldn't match expected type ‘(Char, Bool) -> Bool’ with actual type ‘Char’

I am learning section tautology checker in chapter8 of the book "Programming in Haskell".
There is code which mentions to
eval :: Subst -> Prop -> Bool
eval _ (Const b) = b
eval s (Var x) = find x s
eval s (Not p) = not (eval s p)
eval s (And p q) = eval s p && eval s q
eval s (Imply p q) = eval s p <= eval s q
I'm getting the below error when I do compile this code.
tautology_checker.hs:26:23: error:
• Couldn't match expected type ‘(Char, Bool) -> Bool’
with actual type ‘Char’
• In the first argument of ‘find’, namely ‘x’
In the expression: find x s
In an equation for ‘eval’: eval s (Var x) = find x s
|
26 | eval s (Var x) = find x s
|
I've check for spell correction and typo. It seems to be correct.
My code is here.
Please help me how to resolve this error.
It seems you’re inadvertently using the Prelude’s standard function find, of type:
Foldable t => (a -> Bool) -> t a -> Maybe a
Or, specialised to lists:
(a -> Bool) -> [a] -> Maybe a
Whereas the book wants you to use some other find function, probably defined elsewhere in the text, of a type like:
(Eq a) => a -> [(a, b)] -> b
Or, in your case:
Char -> [(Char, Bool)] -> Bool
You’re giving it x as its first argument, which is of type Char, but it’s expecting a function of type (Char, Bool) -> Bool, because (Char, Bool) is the element type of the list. That’s the source of the type error you got.
You can replace find x s using the standard function lookup:
lookup :: Eq a => a -> [(a, b)] -> Maybe b
Combined with something like fromJust (which throws an error when a variable isn’t bound), e.g., fromJust (lookup x s). You could also use something like find' x s = fromMaybe (error ("unbound variable '" ++ [x] ++ "'")) (lookup x s) for a more detailed error message, or fromMaybe False (which assumes unbound variables are False), using fromMaybe from Data.Maybe.
The function find that ends up being used in your code comes from Data.List and has signature find :: (a -> Bool) -> [a] -> Maybe a. This function tries to find an element of the given list that matches the given predicate.
However, from the way this function is used in your code, you seem to be assuming the signature find :: k -> Assoc k v -> v, with the semantics of locating a value by key in an associative list. This is how I would implement such function:
find :: Eq k => k -> Assoc k v -> v
find k ((k', v) : _) | k == k' = v
find k (_ : tail) = find k tail
I don't have this book, so I can't tell for sure, but my guess is that the book actually defines this function somewhere earlier, probably at the same place it defines the type Assoc itself. You have included the definition of Assoc in your code, but forgot to include the definition of find.
Also note that the function find defined this way is partial: it doesn't know what to return when the given associative list doesn't contain the given key. In order for it to be total, it would need to return Maybe v instead of just v. Just something to keep in mind.

Pattern matching on types

Is there nice way to write the following "x is of type t" parts? (I suspect I should be using Data.Type.Equality but I'm not sure exactly how)
f :: a -> Int
g :: b -> Int
h :: Typeable t => t -> Maybe Int
h x = case x of
(x is of type a) -> Just (f x)
(x is of type b) -> Just (g x)
_ -> Nothing
Follow up question
This is a job for the "type safe cast" bits of Data.Typeable. cast :: (Typeable a, Typeable b) => a -> Maybe b pulls the runtime type information out of the Typeable dictionaries for a and b and compares them; if a and b are the same type then it returns Just its argument, otherwise it fails.
So, with cast and Maybe's Alternative instance in hand, we have:
h x = f <$> cast x
<|> g <$> cast x
As far as I know, there's no way to avoid the repetitious calls to cast, since they occur at different types.

Haskell: safe 'show'

As part of a larger project written in Haskell, I am working on a small utility library to encapsulate common paradigms I use throughout my code. One function (or two functions, rather) that I was working on are fromLeft :: Either a b -> a and fromRight :: Either a b -> b, which are partial functions that are undefined (error to be exact) on antichiral constructors:
fromLeft :: Either a b -> a
fromLeft x = case x of
(Left x) -> x
(Right y) -> error "fromLeft: (Right _)"
fromRight :: Either a b -> b
fromRight x = case x of
(Right x) -> x
(Left y) -> error "fromRight: (Left _)"
In any case, I wanted to extend these functions if possible so that, if the y in the second pattern match for each function were of a type that were showable, it would be printed instead of "_". However, there is no obvious way to go about that without putting a constraint in the signature, which would make these functions lose their generality.
Is there any extension or module voodoo that can selectively perform typeclass functions for instances of those typeclasses and return a general result for other types? More specifically, is there any way in Haskell to write a program that simulates the invalid function
\x -> if (showable x) then show x else "_"
How about this:
fromRightWith :: (a -> String) -> Either a b -> b
fromRightWith show (Left a) = error $ "fromRight: (Left " ++ show a ++ ")"
fromRightWith _ (Right b) = b
fromRight :: Either a b -> b
fromRight = fromRightWith $ const "_"
fromRight' :: Show a => Either a b -> b
fromRight' = fromRightWith show
Then if, in your code, you know that a is an instance of Show, use fromRight'. If not, use fromRight:
instance Show MyError where
show = -- ..
trySomething :: IO (Either MyError Value)
trySomething = --- ..
main = do
value <- fromRight' <$> trySomething
-- ..

Resources