Haskell: How to apply partial order to a substring function? - haskell

I have implemented the class POrd and a substring function, which takes 2 strings and determines if the first string is a substring of the second input string.
Now I want to apply the POrd class to the substring function to make it so that the substrings can be partially ordered.
However I am stuck on how to correctly apply the partial order class (POrd) to the substring function.
class Eq a => POrd a where
pocompare :: a -> a -> Maybe Ordering
(~<), (~>), (~<=), (~>=) :: a -> a -> Bool
-- Minimal complete definition: (~<=) | pocompare
pocompare x y | x == y = Just EQ
| x ~<= y = Just LT
| y ~<= x = Just GT
| otherwise = Nothing
x ~<= y = pocompare x y == Just LT
x ~< y = x ~<= y && x /= y
x ~>= y = y ~<= x
x ~> y = x ~>= y && x /= y
substring :: Eq a => [a] -> [a] -> Bool
substring []_= True
substring _[] = False
substring p#(x:xs) (y:ys) = x == y && prefix xs ys || substring p ys
where
prefix [] _= True
prefix _[] = False
prefix (a:as) (b:bs) = a == b && prefix as bs
instance POrd a => POrd [a] where
(~<=) = substring
xs ~<= ys = substring xs ys
xs ~>= ys = substring ys xs

Related

Parameterizing the binary operation when combining two lists

I'm trying to write a program that takes in two lists and a binary operation and takes each element of one list and applies it to the other using the binary operation. I have it working but not sure how to change it so it works with any binary operator. Here's examples :
myFunction (+) [100,200,300] [4,3,2,1] would return
[96,97,98,99,196,197,198,199,296,297,298,299]
myFunction (+) [100,200,300] [4,3,2,1] would return
[96,97,98,99,196,197,198,199,296,297,298,299]
This is what I have working with specific binary operations
oneEle :: Char -> Integer -> [Integer] -> [Integer]
oneEle a x [] = []
oneEle a x y
| (a == '+') = [p + x | p <- y]
| (a == '-') = [p - x | p <- y]
| (a == '*') = [p * x | p <- y]
| (a == ':') = [p * x | p <- y]
myFunction :: Char -> [Integer] -> [Integer] -> [Integer]
myFunction a [] [] = []
myFunction a [] y = []
myFunction a x [] = []
myFunction a (x:xs) (y:ys) = oneEle a x ([y] ++ ys) ++ myFunction a xs ([y]++ys)
The simplest way is a list comprehension:
myFunction f xs ys = [f x y | x <- xs, y <- ys]
It may not even be worth defining a new function; instead, just inline that content to the call site.
This function is also available from the standard library by the names liftM2 and liftA2.

How can I fix my replace haskell function?

It eill work when : replace :: Eq a => a -> a -> [a] -> [a] will be. How can I convert az a to an [a] in my code ?
replace :: Eq a => a -> [a] -> [a] -> [a]
replace _ _ [] = []
replace a x (y:ys)
| a == y = x : replace a x ys
| otherwise = y : replace a x ys
Example:
replace '?' "a" "" == ""
replace 'a' "e" "alma" == "elme"
replace 'a' "e" "nincsbenne" == "nincsbenne"
You are using wrong operator for the first guard (a == y) - : is used to prepend a head element to a list but x is a list not a single element, so you need to use ++ which concatenates two lists (x and one returned by recursive call):
replace :: Eq a => a -> [a] -> [a] -> [a]
replace _ _ [] = []
replace a x (y:ys)
| a == y = x ++ replace a x ys -- ++ instead of :
| otherwise = y : replace a x ys
Related - Haskell (:) and (++) differences

Couldn't match expected type [a] with actual type Maybe[a]

please pardon for very beginner level quesion.
I am now trying to introduce Maybe into my previous helper function (which swaps the first two elements of the list) to enable empty list error handling:
...haskell
-- | the helper funtion to only swap the first two elements.
swap_first_two_elements :: [a] -> Maybe [a]
swap_first_two_elements list = case list of
x:y:xs -> Just (y:x:xs)
_ -> Nothing
and invoking it in
interprete s x
| x `elem` ["+","-","*","/","^"] = operate x s
| x `elem` ["inc","dec","sqrt","sin","cos","inv"] = operate2 x s
| x `elem` ["+all"] = [sum s]
| x `elem` ["dup"] = (head s) :s
| x `elem` ["pop"] = tail s
| x `elem` ["swap"] = swap_first_two_elements s
| x `elem` ["clear"] = drop (length s) s
| x `elem` ["*all"] = [product s]
| otherwise = read x:s
where
operate op (x:y:s) = case op of
"+" -> x + y:s
"-" -> y - x:s
"*" -> x * y:s
"/" -> y / x:s
"^" -> y ** x:s
But I am getting an error like
Couldn't match expected type [a] with actual type Maybe[a]
I read other related posts and modified it like:
| x `elem` ["swap"] = swap_first_two_elements Just(s)
Still got error. Could experts offer where I go wrong? Thank you.
So you have
interprete s x
| x `elem` ["pop"] = tail s
| x `elem` ["swap"] = swap_first_two_elements s
Now,
tail :: [a] -> [a]
but
swap_first_two_elements :: [a] -> Maybe [a]
and of course those are two different types altogether.
You can't return a value of one type in some case, and of another type altogether in some other cases. All cases in a function definition must return values of the same type.
A function goes from a type to a type, not to types.
You can fix your definition by wrapping all the other cases' values in a Just, like so:
| x `elem` ["pop"] = Just (tail s)
Just for your code to have more sense, I think you need to spread the Maybe all over the sub-functions, for example in operate, and pop and all other "unsafe" functions, you can take advantage of Maybe type, like divide by 0:
interprete s x
| x `elem` ["+","-","*","/","^"] = operate x s
| x `elem` ["inc","dec","sqrt","sin","cos","inv"] = Just (operate2 x s)
| x `elem` ["+all"] = Just([sum s])
| x `elem` ["dup"] = dup s
| x `elem` ["pop"] = pop s
| x `elem` ["swap"] = swap_first_two_elements s
| x `elem` ["clear"] = Just []
| x `elem` ["*all"] = Just([product s])
| otherwise = Just(read x:s)
pop [] = Nothing
pop (x:xs) = Just xs
dup [] = Nothing
dup s#(x:xs) = Just (x:s)
operate op (x:y:s) = case op of
"+" -> Just(x + y:s)
"-" -> Just(y - x:s)
"*" -> Just( x * y:s)
"/" -> case x of
0 -> Nothing
n -> Just(y / x:s)
"^" -> Just(y ** x:s)
operate _ _ = Nothing
swap_first_two_elements :: [a] -> Maybe [a]
swap_first_two_elements (x:y:xs) = Just (y:x:xs)
swap_first_two_elements _ = Nothing
operate2 = undefined
I don't know what operate2 does, so, I leave it to you. But by sure, it has type [a] -> Maybe [a], so please, make it return a Maybe [a], please.

How can I extract list of similar elements from a haskell list

Given a list such as [1,0,0,0,3,0,0,0,0,2,4,0,0] and an index, how can I extract consecutive patterns of 0 in Haskell. For example if the given index is between 1 and 3 inclusive, the result is [0,0,0] if it is between 5 and 8 [0,0,0,0] and so on
First, build a list where run lengths are stored for each number:
runs :: (Eq a) => [a] -> [(a, Int)]
runs = map (head &&& length) . group
so e.g.
runs [1,0,0,0,1,0,0,0,0,1,1,0,0] == [(1,1),(0,3),(1,1),(0,4),(1,2),(0,2)]
Then, index into this list by walking it in run length-sized steps:
indexRuns :: Int -> [(a, Int)] -> [a]
indexRuns i [] = error "Index out of bounds"
indexRuns i ((x, l):rs)
| i < l = replicate l x
| otherwise = indexRuns (i - l) rs
You can do this in O(n) time:
extract :: Eq a => Int -> [a] -> [a]
extract _ [] = []
extract idx (x:xs) = extract' x [x] 1 xs
where
extract' _ _ _ [] = [] -- Index out of bounds
extract' v vs n (r : rest)
| idx == n = vs ++ (takeWhile (== v) rest)
| (v == r) = extract' v (r:vs) (n+1) rest
| otherwise = extract' r [r] (n+1) rest
This will count the number of zeros around the index
numZeros::Int->[Int]->Int
numZeros 0 (1:_) = 0
numZeros i (1:rest) = numZeros (i-1) rest
numZeros i theList
| i < zeroLen = zeroLen
| otherwise = numZeros (i-zeroLen) $ drop zeroLen theList
where
zeroLen = length (takeWhile (==0) theList)
You can replicate 0 the appropriate number of times to get the final list.
f = f' (takeWhile (== 0)) where
f' c n xs | n < 0 || null xs = []
f' c n (1:xs) = f (n - 1) xs
f' c 0 xs = c xs
f' c n (0:xs) = f' ((0:) . c) (n - 1) xs
Or even more obfuscated
f n xs = g (splitAt n xs) >>= takeWhile (== 0) where
g (xs, ys#(0:_)) = [reverse xs, ys]
g _ = []
Some tests:
main = mapM_ (\i -> print $ (i, f i [1,0,0,0,1,0,0,0,0,1,1,0,0])) [-1..13]
prints
(-1,[])
(0,[])
(1,[0,0,0])
(2,[0,0,0])
(3,[0,0,0])
(4,[])
(5,[0,0,0,0])
(6,[0,0,0,0])
(7,[0,0,0,0])
(8,[0,0,0,0])
(9,[])
(10,[])
(11,[0,0])
(12,[0,0])
(13,[])

how can i count prefixes in haskell?

I want to create a function in haskell, that returns the number of times a single word is a prefix of a list of words. For example: for the word "go" and the list of words ["ace","going", "gone", "golf"], it should return 3. What I have so far is this:
numberOfPrefixes _ [] = error ("Empty list of strings")
numberOfPrefixes [] _ = error ("No word")
numberOfPrefixes (x:xs) (y:ys)
| isPrefixOf (x:xs) y = 1 + numberOfPrefixes(x:xs) ys
| otherwise = 0
But this only works if the first element of the list of words is actually a prefix. If the first element is not a prefix, the whole thing falls apart. Any help making this right?
isPrefixOf :: (Eq a) => [a] -> [a] -> Bool
isPrefixOf [] _ = True
isPrefixOf _ [] = False
isPrefixOf (x:xs) (y:ys) = x == y && isPrefixOf xs ys
Here's how I'd write this
(.:) :: (b -> c) -> (a -> a1 -> b) -> a -> a1 -> c
(.:) = (.) . (.) -- A common utility definition
infixr 9 .:
prefixCount :: Eq a => [a] -> [[a]] -> Integer
prefixCount = length .: filter . isPrefixOf
Or writing it pointfully
prefixCount l ls = length $ filter (isPrefixOf l) ls
If you really want to write it recursively
prefixCount l [] = 0
prefixCount x (l:ls) | <is prefix?> = 1 + prefixCount x ls
| otherwise = prefixCount x ls
and just fill in <is prefix?> with a check whether x is a prefix is of l

Resources