Haskell - please help me simplify these two functions - haskell

I am trying to work through the exercises in Write Yourself a Scheme in 48 Hours. I need help with simplifying couple of functions.
data LispVal = Number Integer
| String String
| Bool Bool
isNumber :: [LispVal] -> LispVal
isNumber [] = Bool False
isNumber [(Number _)] = Bool True
isNumber ((Number _):xs) = isNumber xs
isNumber _ = Bool False
isString :: [LispVal] -> LispVal
isString [] = Bool False
isString [(String _)] = Bool True
isString ((String _):xs) = isString xs
isString _ = Bool False
The isNumber and isString functions have lot common structure. How do I go about factoring out this common structure?

While you can't parameterize the pattern match itself, you can write yourself small helper functions so you at least don't have to repeat the list handling for every function:
isString (String _) = True
isString _ = False
isNumber (Number _) = True
isNumber _ = False
all1 _ [] = False
all1 f xs = all f xs
isListOfStrings = Bool . all1 isString
isListOfNumbers = Bool . all1 isNumber
In my opinion, the special case handling of the empty list isn't consistent here. You should consider just using all instead (so that the empty list can be a list of any kind, similar to how Haskell's lists work).

Related

What does this statement mean in Haskell?

I'm currently still getting to know more about Haskell, under the topic of Pattern Matching, what does it mean by _ && _ = False in Haskell? I came across this statement in one of the lecture slides, like what does it mean by the underscores? Thanks again!
The underscores are wildcards. That is, they match any value, but do not bind the value to a name. A common example of this usage is:
True && True = True
_ && _ = False
Underscores means a wildcard. It binds with any value. It thus means that for any value for the left and right operand for the given type of the function, it will fire that clause, and thus return False.
One can thus define (&&) :: Bool -> Bool -> Bool with:
(&&) :: Bool -> Bool -> Bool
True && True = True
_ && _ = False
The real implementation of (&&) is however lazy in its second parameter, and is implemented asĀ [src]:
-- | Boolean \"and\"
(&&) :: Bool -> Bool -> Bool
True && x = x
False && _ = False

Using filter with custom datatypes

I have these datatypes:
data Command = Back Int | Front Val deriving (Show,Eq)
data Val = Val {first::Int, second::Int, third::Int} deriving (Show, Eq)
type Program = [Command]
I have this function:
foo :: Program -> Int
foo list = length (filter (==Front Val {first, second, third}) list)
The purpose is to find how many times a Front occurs USING FILTER ONLY, and foo gives compilation error. I am not sure how to represent the integer/val part of Front.
You can not use an equality check (==) :: Eq a => a -> a -> Bool with variables like first and second, if these do not have a value. What you need here is pattern matching.
We can for example use list comprehension:
foo :: Program -> Int
foo list = length [ v | v#(Front _) <- list ]
There is no need to match the parameter with Val {}, or Val _ _ _, etc. since the only data constructor for the Val type is Val.
In case you think you will later add more data constructors, you can however add an extra subpattern:
foo :: Program -> Int
foo list = length [ v | v#(Front (Val {})) <- list ]
Or we can do the pattern matching in a function and use filter :: (a -> Bool) -> [a] -> [a], like:
foo :: Program -> Int
foo = length . filter f
where f (Front _) = True
f _ = False
or if we include the Val data constructor check:
foo :: Program -> Int
foo = length . filter f
where f (Front (Val {})) = True
f _ = False
As #WillemVanOnsem said in his answer, the approach you're using doesn't work. Try using filter (\x -> case x of { Front _ -> True; Back _ -> False }) list. You may be able to work out how this works from that alone, but if you need any more details:
\x -> case x of { Front _ -> True; Back _ -> False } is a lambda expression. It defines an unnamed (or anonymous) function which takes one parameter, named x, and returns the value given by case x of { Front _ -> True; Back _ -> False }.
case x of { Front _ -> True; Back _ -> False } does pattern matching on x. If x is of the form Front _, where _ can be anything, then it returns True; otherwise it returns False. Normally this statement would be formatted like this:
case x of
Front _ -> True
Back _ -> False
But the compact syntax above is shorter and so works better in this case.
The lambda expression above - which as discussed returns True when its argument is of the form Front _ - is then passed to filter as its argument.

Operator & in haskell?

How to check the second argument between an operation of true and false in haskell? E.g, False && True will only check the first argument and then will stop the operation. Is there something like False & True in Haskell to check both arguments?
&& in the prelude is implemented as
(&&) :: Bool -> Bool -> Bool
True && x = x
False && _ = False
Which means in the case that the first argument is False the second
one is never evaluated. You could always implement your own version to have the behaviour that you want e.g.:
(.&&.) :: Bool -> Bool -> Bool
True .&&. x = x
False .&&. False = False
False .&&. True = False
In which the second second argument is evaluated in either case.
There is no good reason why you'd want this, but if you insist...
import Control.Parallel (pseq)
(&&!) :: Bool -> Bool -> Bool
a &&! b = b `pseq` (a&&b)
Usually, seq (which doesn't require any imports) will also suffice instead of pseq, but only the latter actually guarantees that b will be evaluated.
Of course, the semantics of this function will be exactly the same as && alone, it will just be slower in some cases.
I was mislead by the OP's subject "Operator & in haskell?"
For those who are here looking for (&) in Haskell
& is a reverse application operator in Data.Function
(&) :: a -> (a -> b) -> b

Haskell String substring function

My function takes 2 strings and determines if the first string is a substring of the second input string. For instance:
isSubb "abc" "abcmhk" -- True
isSubb "abc" "uyabcmhk" -- True
isSubb "abc" "okaibcmhk" -- False
isSubb "abc" "amnabkaaabcmhk" -- gives True
So far I have:
isSubb :: [Char] -> [Char] -> Bool
isSubb sub str = auxx sub sub str
auxx :: [Char] -> [Char] -> [Char] -> Bool
auxx safe (s:ub) (st:r)
| s:ub == [] = True
| st:r == [] = False
| s == st = auxx safe ub r
| otherwise = auxx safe safe r
But its giving me a non-exhaustive error on the auxx function.
Any help is greatly appreciated!
Thank you!
In Data.List there is the isInfixOF function.
isInfixOf :: Eq a => [a] -> [a] -> Bool
The isInfixOf function takes two lists and returns True iff the first list is contained, wholly and intact, anywhere within the second.
Prelude Data.List> isInfixOf "abc" "abcmhk"
True
Prelude Data.List> isInfixOf "abc" "uyabcmhk"
True
Prelude Data.List> isInfixOf "abc" "okaibcmhk"
False
Prelude Data.List> isInfixOf "abc" "amnabkaaabcmhk"
True
You could write your function like
import Data.List (isInfixOf)
isSubb :: [Char] -> [Char] -> Bool
isSubb sub str = isInfixOf sub str
Your auxx function needs to take into account the cases where the second or the third parameters are [] (because you are getting there).
The s:ub == [] and st:r == [] will never be True since pattern matching happens before guard evaluation.
A sane equivalent of you function would be
auxx safe sub str
| sub == [] = True
| str == [] = False
| head sub == head str = auxx safe ub r
| otherwise = auxx safe safe r
Though the above is not efficient since it can be improved by pattern matching.
auxx _ [] _ = True
auxx _ _ [] = False
auxx safe (s:ub) (st:r)
| s == st = auxx safe ub r
| otherwise = auxx safe safe r
Your definition is not correct!
| s == st = auxx safe ub r
gives problems. Look, determining whether "abc" is in "afkjskgsbc" is not the same as determining whether "bc" is in "fkjskgsbc" . So you need to consider that the first letter may or may not be a part of the string you're looking for.

Haskell pattern matching - how to use constants variable

I would ideally like to write something like this:
myValue1 = 1 :: Int
myValue2 = 2 :: Int
myFunc :: Int -> Bool
myFunc myValue1 = True
myFunc myValue2 = False
Calling myFunc myValue2 returns True - not what I intend. I know why this happens, but is there a way to express this in Haskell without resorting to C-style #define statements?
Well, Haskell doesn't unify names like this. Those new 'myValue1' and '2' identifiers are new variables you're binding.
The most Haskelly way is to use strong types and pattern matching:
data Values
= D1
| D2
myFunc :: Values -> Bool
myFunc D1 = True
myFunc D2 = False
Giving you a static guarantee only "1" or "2" can be passed to myFunc, proper symbolic matching and you even retain conversion to integers by deriving Enum.
You cannot match against variable values as Don explained.
But you can use guards in this case:
myValue1 = 1 :: Int
myValue2 = 2 :: Int
myFunc :: Int -> Bool
myFunc x
| x == myValue1 = True
| x == myValue2 = False
If you don't want to create another data type, the usual solution is to use guards:
myValue1 = 1 :: Int
myValue2 = 2 :: Int
myFunc :: Int -> Bool
myFunc val | val == myValue1 = True
| val == myValue2 = False
What you put after the pipe can be any boolean condition; if it's true, the corresponding function body will be run.
If the idea is just to define some constants to use in patterns, you can also use the language extension PatternSynonyms:
{-# LANGUAGE PatternSynonyms #-}
pattern MyValue1 = 1
pattern MyValue2 = 2
myFunc :: Int -> Bool
myFunc MyValue1 = True
myFunc MyValue2 = False

Resources