What is the best way to map across a list, using the result of each map as you go along, when your result is of a different type to the list.
for example
f :: Int -> Int -> String -> String
l = [1,2,3,4]
I would like to have something that walks along the list l and does:
f 1 2 [] = result1 => f 2 3 result1 = result2 => f 3 4 result3 ==> return result3.
I can sort of get this to work with a an accumulator, but it seems rather cumbersome. Is there a standard way to do this... or is this something for Monads??
Thanks!
NB the function above is just for illustration.
This is just a fold left over the pairs in the input list:
f :: Int -> Int -> String -> String
f = undefined
accum :: [Int] -> String
accum xs = foldl (flip . uncurry $ f) "" $ zip xs (drop 1 xs)
You probably want to use Data.List.foldl' instead of foldl, but this is an answer that works with just Prelude.
Seems like a job for fold:
func f l = foldl (\s (x, y) -> f x y s) "" (zip l (tail l))
-- just some placeholder function
f :: Int -> Int -> String -> String
f x y s = s ++ " " ++ show(x) ++ " " ++ show(y)
l = [1,2,3,4]
main = print $ func f l
prints:
" 1 2 2 3 3 4"
(if you can change the signature of f, you can get rid of the ugly lambda that rearranges arguments)
Of course, rather than zipping, you could pass along the previous element inside the fold's accumulator. For example:
l = [1,2,3,4]
f x y = (x,y)
g b#(accum,prev) a = (accum ++ [f prev a],a)
main = print (foldl g ([],head l) (tail l))
Output:
([(1,2),(2,3),(3,4)],4)
Related
How can I apply a function to only a single element of a list?
Any suggestion?
Example:
let list = [1,2,3,4,3,6]
function x = x * 2
in ...
I want to apply function only to the first occurance of 3 and stop there.
Output:
List = [1,2,6,4,3,6] -- [1, 2, function 3, 4, 3, 6]
To map or not to map, that is the question.
Better not to map.
Why? Because map id == id anyway, and you only want to map through one element, the first one found to be equal to the argument given.
Thus, split the list in two, change the found element, and glue them all back together. Simple.
See: span :: (a -> Bool) -> [a] -> ([a], [a]).
Write: revappend (xs :: [a]) (ys :: [a]) == append (reverse xs) ys, only efficient.
Or fuse all the pieces together into one function. You can code it directly with manual recursion, or using foldr. Remember,
map f xs = foldr (\x r -> f x : r) [] xs
takeWhile p xs = foldr (\x r -> if p x then x : r else []) [] xs
takeUntil p xs = foldr (\x r -> if p x then [x] else x : r) [] xs
filter p xs = foldr (\x r -> if p x then x : r else r) [] xs
duplicate xs = foldr (\x r -> x : x : r) [] xs
mapFirstThat p f xs = -- ... your function
etc. Although, foldr won't be a direct fit, as you need the combining function of the (\x xs r -> ...) variety. That is known as paramorphism, and can be faked by feeding tails xs to the foldr, instead.
you need to maintain some type of state to indicate the first instance of the value, since map will apply the function to all values.
Perhaps something like this
map (\(b,x) -> if (b) then f x else x) $ markFirst 3 [1,2,3,4,3,6]
and
markFirst :: a -> [a] -> [(Boolean,a)]
markFirst a [] = []
markFirst a (x:xs) | x==a = (True,x): zip (repeat False) xs
| otherwise = (False,x): markFirst a xs
I'm sure there is an easier way, but that's the best I came up with at this time on the day before Thanksgiving.
Here is another approach based on the comment below
> let leftap f (x,y) = f x ++ y
leftap (map (\x -> if(x==3) then f x else x)) $ splitAt 3 [1,2,3,4,3,6]
You can just create a simple function which multiples a number by two:
times_two :: (Num a) => a -> a
times_two x = x * 2
Then simply search for the specified element in the list, and apply times_two to it. Something like this could work:
map_one_element :: (Eq a, Num a) => a -> (a -> a) -> [a] -> [a]
-- base case
map_one_element _ _ [] = []
-- recursive case
map_one_element x f (y:ys)
-- ff element is found, apply f to it and add rest of the list normally
| x == y = f y : ys
-- first occurence hasnt been found, keep recursing
| otherwise = y : map_one_element x f ys
Which works as follows:
*Main> map_one_element 3 times_two [1,2,3,4,3,6]
[1,2,6,4,3,6]
How is it possible to compose n maps in Haskell?
I've tried doing it recursively:
composeMap 0 f = (\x -> x)
composeMap n f = (.) f (composeMap (n-1) f)
And iteratively:
composeMap' n k f g =
if n == k then g
else composeMap' n (k+1) f (f . g)
composeMap n f = composeMap' n 0 f (\x -> x)
But to no avail. Haskell thinks I am constructing an infinite type.
This is obviously false as the function defined is finite for any
n >= 0.
Any suggestions?
Some have posted solutions treating f as having the following type signature:
f :: a -> a
However, I want this to work for f s.t. f is polymorphic in the following way:
f :: a -> a'
f :: a' -> a''
In particular, I want a function that works for the function map, with possible type signatures:
map :: (a -> b) -> [a] -> [b]
map (polymorphic) :: ([a] -> [b]) -> [[a]] -> [[b]]
The function compiles perfectly fine, but Haskell infers the following type signature, which is not what I want:
composeMap'' :: Int -> (b -> b) -> b -> b
I've even tried wrapping map in a monad, but Haskell still thinks I'm constructing an infinite type:
composeMap n f = foldl (>>=) f (replicate n (\x -> return (map x)))
Edit:
I got what I want with the following template Haskell code. Pretty sweet.
This is for declaring the composed map functions:
composeMap :: Int -> Q Dec
composeMap n
| n >= 1 = funD name [cl]
| otherwise = fail "composeMap: argument n may not be <= 0"
where
name = mkName $ "map" ++ show n
composeAll = foldl1 (\fs f -> [| $fs . $f |])
funcs = replicate n [| map |]
composedF = composeAll funcs
cl = clause [] (normalB composedF) []
This is for inlining the composed map. It is more flexible:
composeMap :: Int -> Q Exp
composeMap n = do
f <- newName "f"
maps <- composedF
return $ LamE [(VarP f)] (AppE maps (VarE f))
where
composeAll = foldl1 (\fs f -> [| $fs . $f |])
funcs = replicate n [| map |]
composedF = composeAll funcs
Also, the guys who put the question on hold didn't even understand the question in the first place...
I am afraid I am missing something. Your first implementation compiles and works fine for me (ghc 8.0.2).
Your second implementation failed to compile because you forgot the ' in the else clause. Here is my complete source file:
composeMap1 0 f = (\x -> x)
composeMap1 n f = (.) f (composeMap1 (n-1) f)
composeMap2' n k f g =
if n == k then g
else composeMap2' n (k+1) f (f . g)
composeMap2 n f = composeMap2' n 0 f (\x -> x)
And some tests
λ: :l question.hs
[1 of 1] Compiling Main ( question.hs, interpreted )
Ok, modules loaded: Main.
λ: doubleQuote = composeMap1 2 (\x -> "'" ++ x ++ "'")
λ: doubleQuote "something"
"''something''"
λ: doubleQuote = composeMap2 2 (\x -> "'" ++ x ++ "'")
λ: doubleQuote "something"
"''something''"
λ: plusThree = composeMap1 3 (+1)
λ: plusThree 10
13
λ: plusThree = composeMap2 3 (+1)
λ: plusThree 10
13
my title might be a bit off and i'll try to explain a bit better what i'm trying to achieve.
Basically let's say i have a list:
["1234x4","253x4",2839",2845"]
Now i'd like to add all the positions of the strings which contain element 5 to a new list. On a current example the result list would be:
[1,3]
For that i've done similar function for elem:
myElem [] _ = False
myElem [x] number =
if (firstCheck x) then if digitToInt(x) == number then True else False else False
myElem (x:xs) number =
if (firstCheck x) then (if digitToInt(x) == number then True else myElem xs number) else myElem xs number
where firstCheck x checks that the checked element isn't 'x' or '#'
Now in my current function i get the first element position which contains the element, however my head is stuck around on how to get the full list:
findBlock (x:xs) number arv =
if myElem x number then arv else findBlock xs number arv+1
Where arv is 0 and number is the number i'm looking for.
For example on input:
findBlock ["1234x4","253x4",2839",2845"] 5 0
The result would be 1
Any help would be appreciated.
The function you want already exists in the Data.List module, by the name of findIndices. You can simply use (elem '5') as the predicate.
http://hackage.haskell.org/package/base-4.8.1.0/docs/Data-List.html#v:findIndices
If, for some reason, you're not allowed to use the built-in one, it comes with a very pretty definition (although the one actually used has a more complicated, more efficient one):
findIndices p xs = [ i | (x,i) <- zip xs [0..], p x]
By the way, I found this function by searching Hoogle for the type [a] -> (a -> Bool) -> [Int], which (modulo parameter ordering) is obviously the type such a function must have. The best way to find out of Haskell has something is to think about the type it would need to have and search Hoogle or Hayoo for the type. Hoogle is better IMO because it does slightly fuzzy matching on the type; e.g. Hayoo wouldn't find the function here by the type I've given, because it take the arguments in the reverse order.
An implementation of findIndices, for instructional purposes:
findIndices ok list = f list 0 where
f [] _ = []
f (x:xs) ix
| ok x = ix : f xs (ix+1)
| otherwise = f xs (ix+1)
Use it like findIndices (elem '5') my_list_o_strings
You're trying to work your way through a list, keeping track of where you are in the list. The simplest function for doing this is
mapWithIndex :: (Int -> a -> b) -> [a] -> [b]
mapWithIndex = mwi 0 where
mwi i _f [] = i `seq` []
mwi i f (x:xs) = i `seq` f i x : mwi (i+1) f xs
This takes a function and a list, and applies the function to each index and element. So
mapWithIndex (\i x -> (i, x)) ['a', 'b', 'c'] =
[(0,'a'), (1,'b'),(2,'c')]
Once you've done that, you can filter the list to get just the pairs you want:
filter (elem '5' . snd)
and then map fst over it to get the list of indices.
A more integrated approach is to use foldrWithIndex.
foldrWithIndex :: (Int -> a -> b -> b) -> b -> [a] -> b
foldrWithIndex = fis 0 where
fis i _c n [] = i `seq` n
fis i c n (x:xs) = i `seq` c i x (fis (i+1) c n xs)
This lets you do everything in one step.
It turns out that you can implement foldrWithIndex using foldr pretty neatly, which makes it available for any Foldable container:
foldrWithIndex :: (Foldable f, Integral i) =>
(i -> a -> b -> b) -> b -> f a -> b
foldrWithIndex c n xs = foldr go (`seq` n) xs 0 where
go x r i = i `seq` c i x (r (i + 1))
Anyway,
findIndices p = foldrWithIndex go [] where
go i x r | p x = i : r
| otherwise = r
List functions allow us to implement arbitrarily-dimensional vector math quite elegantly. For example:
on = (.) . (.)
add = zipWith (+)
sub = zipWith (-)
mul = zipWith (*)
dist = len `on` sub
dot = sum `on` mul
len = sqrt . join dot
And so on.
main = print $ add [1,2,3] [1,1,1] -- [2,3,4]
main = print $ len [1,1,1] -- 1.7320508075688772
main = print $ dot [2,0,0] [2,0,0] -- 4
Of course, this is not the most efficient solution, but is insightful to look at, as one can say map, zipWith and such generalize those vector operations. There is one function I couldn't implement elegantly, though - that is cross products. Since a possible n-dimensional generalization of cross products is the nd matrix determinant, how can I implement matrix multiplication elegantly?
Edit: yes, I asked a completely unrelated question to the problem I set up. Fml.
It just so happens I have some code lying around for doing n-dimensional matrix operations which I thought was quite cute when I wrote it at least:
{-# LANGUAGE NoMonomorphismRestriction #-}
module MultiArray where
import Control.Arrow
import Control.Monad
import Data.Ix
import Data.Maybe
import Data.Array (Array)
import qualified Data.Array as A
-- {{{ from Dmwit.hs
deleteAt n xs = take n xs ++ drop (n + 1) xs
insertAt n x xs = take n xs ++ x : drop n xs
doublify f g xs ys = f (uncurry g) (zip xs ys)
any2 = doublify any
all2 = doublify all
-- }}}
-- makes the most sense when ls and hs have the same length
instance Ix a => Ix [a] where
range = sequence . map range . uncurry zip
inRange = all2 inRange . uncurry zip
rangeSize = product . uncurry (zipWith (curry rangeSize))
index (ls, hs) xs = fst . foldr step (0, 1) $ zip indices sizes where
indices = zipWith index (zip ls hs) xs
sizes = map rangeSize $ zip ls hs
step (i, b) (s, p) = (s + p * i, p * b)
fold :: (Enum i, Ix i) => ([a] -> b) -> Int -> Array [i] a -> Array [i] b
fold f n a = A.array newBound assocs where
(oldLowBound, oldHighBound) = A.bounds a
(newLowBoundBeg , dimLow : newLowBoundEnd ) = splitAt n oldLowBound
(newHighBoundBeg, dimHigh: newHighBoundEnd) = splitAt n oldHighBound
assocs = [(beg ++ end, f [a A.! (beg ++ i : end) | i <- [dimLow..dimHigh]])
| beg <- range (newLowBoundBeg, newHighBoundBeg)
, end <- range (newLowBoundEnd, newHighBoundEnd)
]
newBound = (newLowBoundBeg ++ newLowBoundEnd, newHighBoundBeg ++ newHighBoundEnd)
flatten a = check a >> return value where
check = guard . (1==) . length . fst . A.bounds
value = A.ixmap ((head *** head) . A.bounds $ a) return a
elementWise :: (MonadPlus m, Ix i) => (a -> b -> c) -> Array i a -> Array i b -> m (Array i c)
elementWise f a b = check >> return value where
check = guard $ A.bounds a == A.bounds b
value = A.listArray (A.bounds a) (zipWith f (A.elems a) (A.elems b))
unsafeFlatten a = fromJust $ flatten a
unsafeElementWise f a b = fromJust $ elementWise f a b
matrixMult a b = fold sum 1 $ unsafeElementWise (*) a' b' where
aBounds = (join (***) (!!0)) $ A.bounds a
bBounds = (join (***) (!!1)) $ A.bounds b
a' = copy 2 bBounds a
b' = copy 0 aBounds b
bijection f g a = A.ixmap ((f *** f) . A.bounds $ a) g a
unFlatten = bijection return head
matrixTranspose = bijection reverse reverse
copy n (low, high) a = A.ixmap (newBounds a) (deleteAt n) a where
newBounds = (insertAt n low *** insertAt n high) . A.bounds
The cute bit here is matrixMult, which is one of the only operations that is specialized to two-dimensional arrays. It expands its first argument along one dimension (by putting a copy of the two-dimensional object into each slice of the three-dimensional object); expands its second along another; does pointwise multiplication (now in a three-dimensional array); then collapses the fabricated third dimension by summing. Quite nice.
I want to filter a string with a string.
What I want is to use delete every first occurring char.
myFunc :: String -> String -> String
Like:
myFunc "dddog" "bigdddddog" = "biddg"
In "dddog": 3x d, 1x o, 1x g
In the second string it removed 3x d, 1x o and 1x g
So the output: biddg
I can't use filter for it, because it will delete all occurring chars.
And I struggled a long time with it.
Thanks in advance:)
How about
Prelude> :m +Data.List
Prelude Data.List> "bigdddddog" \\ "dddog"
"biddg"
Not the nicest solution, but you can understand easier what's going on:
myfunc :: String -> String -> String
myfunc [] xs = xs
myfunc (x:xs) ys = myfunc xs $ remove x ys
where
remove _ [] = []
remove x (y:ys) = if x == y then ys else y : remove x ys
As you commented, you want to use guards. Do you mean this?
myfunc :: String -> String -> String
myfunc [] xs = xs
myfunc (x:xs) ys = myfunc xs $ remove x ys
remove :: Char -> String -> String
remove _ [] = []
remove x (y:ys)
| x == y = ys
| otherwise = y : remove x ys
some of the other solutions don't seem to produce the same result you posted. I think I have a simple solution that does what you asked for but I may be misunderstanding what you want. All I do in the following code is go though the list and apply 'delete' to every element in the list. It's not exactly efficient but it gets the job done.
import Data.List
myFunc (x:xs) ys = myFunc xs (delete x ys)
myFunc [] ys = ys
There are perhaps more efficient solutions like storing the "to remove" list in a tree with the number of occurences stored as the value then traversing the main list testing to see if the count at that key was still greater than zero. I think that would give you O(n*lg(m)) (where n is the size of the list to be removed from and m is the size of the "to remove" list) rather than O(n*m) as is the case above. This version could also be maid to be lazy I think.
edit:
Here is the tree version I was talking abut using Data.Map. It's a bit complex but should be more efficient for large lists and it is somewhat lazy
myFunc l ys = myFunc' (makeCount l) ys
where makeCount xs = foldr increment (Map.fromList []) xs
increment x a = Map.insertWith (+) x 1 a
decrement x a = Map.insertWith (flip (-)) x 1 a
getCount x a = case Map.lookup x a of
Just c -> c
Nothing -> 0
myFunc' counts (x:xs) = if (getCount x counts) > 0
then myFunc' (decrement x counts) xs
else x : myFunc' counts xs
myFunc' _ [] = []
I am not quite sure about how you want your function to behave, how about this?
import Data.List (isPrefixOf)
myFunc :: String -> String -> String
myFunc _ [] = []
myFunc y x'#(x:xs) | y `isPrefixOf` x' = drop (length y) x'
| otherwise = x : myFilter xs y
This gives the following output in GHCi:
> myFunc "dddog" "bigdddddog"
> "bigdd"
If this is not what you had in mind, please give another input/output example.
I like kaan's elegant solution. In case you meant this...here's one where the "ddd" would only be removed if matched as a whole:
import Data.List (group,isPrefixOf,delete)
f needles str = g (group needles) str where
g needles [] = []
g needles xxs#(x:xs)
| null needle' = [x] ++ g needles xs
| otherwise = let needle = head needle'
in g (delete needle needles) (drop (length needle) xxs)
where needle' = dropWhile (not . flip isPrefixOf xxs) needles
Output:
*Main> f "dddog" "bigdddddog"
"biddg"
*Main> f "dddog" "bdigdogd"
"bdidgd"
No monadic solution yet, there you go:
import Control.Monad.State
myFunc :: String -> State String String
myFunc [] = return ""
myFunc (x:xs) = get >>= f where
f [] = return (x:xs)
f (y:ys) = if y == x then put ys >> myFunc xs
else myFunc xs >>= return . (x:)
main = do
let (a,b) = runState (myFunc "bigdddddog") "dddog" in
putStr a
Using predefined functions from Data.List,
-- mapAccumL :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])
-- lookup :: (Eq a) => a -> [(a, b)] -> Maybe b
{-# LANGUAGE PatternGuards #-}
import Data.List
picks [] = [] -- http://stackoverflow.com/a/9889702/849891
picks (x:xs) = (x,xs) : [ (y,x:ys) | (y,ys) <- picks xs]
myFunc a b = concat . snd $ mapAccumL f (picks a) b
where
f acc x | Just r <- lookup x acc = (picks r,[])
f acc x = (acc,[x])
Testing:
Prelude Data.List> myFunc "dddog" "bigdddddog"
"biddg"
edit: this is of course a bit more complex than (\\). I'll let it stand as an illustration. There could be some merit to it still, as it doesn't copy the 2nd (longer?) string over and over, for each non-matching character from the 1st (shorter) string, as delete apparently does, used in (\\) = foldl (flip delete).