I'm testing my functions for transposing a matrix(type matrix = float list list) in OCaml, here's my code:
(* get the first column of the matrix *)
let rec get_column (a: matrix): float list =
match a with
| [] -> []
| x :: xs ->
(match x with
| [] -> []
| h :: t -> h :: get_column xs)
(* get the rest of the element in the matrix *)
let rec get_tail (a: matrix): matrix =
match a with
| [] -> []
| x :: xs ->
(match x with
| [] -> []
| h :: t -> t :: get_tail xs)
(* find the transpose of a matrix *)
let rec transpose (lss : matrix) : matrix =
match lss with
| [] -> []
| _ -> get_column lss :: transpose (get_tail lss)
When I tested it out, there's a redundant [] at the very end and I don't why.
So for example, the output of:
transpose[[0.; 4.; 8.]; [1.; 5.; 9.]; [2.; 6.; 10.]; [3.; 7.; 11.]]
should be
[[0.; 1.; 2.; 3.]; [4.; 5.; 6.; 7.]; [8.; 9.; 10.; 11.]]
But my code output is:
[[0.; 1.; 2.; 3.]; [4.; 5.; 6.; 7.]; [8.; 9.; 10.; 11.]; []]
First, you can simplify your pattern matching significantly.
let rec get_column (a: matrix): float list =
match a with
| [] | []::_ -> []
| (h::_)::xs -> h :: get_column xs
let rec get_tail (a: matrix): matrix =
match a with
| [] | []::_ -> []
| (_::t)::xs -> t :: get_tail xs
Having done that, let's look at how a simple call to transpose is evaluated.
transpose [[1.; 2.]; [3.; 4.]]
[1.; 3.] :: transpose [[2.]; [4.]]
[1.; 3.] :: [2.; 4.] :: transpose [[]; []]
[1.; 3.] :: [2.; 4.] :: [] :: transpose []
[1.; 3.] :: [2.; 4.] :: [] :: []
[[1.; 3.]; [2.; 4.]; []]
Essentially what you're doing is getting the head of every list. This can be done with List.map (you can implement your own version if you must).
let get_column lss =
List.(map hd lss)
Your get_tail function is basically just:
let get_tail lss =
List.(map tl lss)
For every element in the first row, you want to retrieve each column.
let rec transpose lss =
match lss with
| []::_ | [] -> []
| (h::t)::xs ->
let heads = h :: List.(map hd xs) in
let tails = t :: List.(map tl xs) in
heads :: transpose tails
For this kind of bugs, you should test the simplest case that exhibits the issue. In your case, that would be transpose [[0.]]. Since the example is very small, you can trace the execution of your transpose function by hand and catch the issue.
merge :: [a] -> [a] -> [a]
merge xs [] = xs
merge [] ys = ys
merge (x:xs) (y:ys) = x : y : merge xs ys
I have got this working but now I need to sort them in ascending order.
You just need to compare x and y and decide which to add to the result first. Note that you only add one at a time; the next element after x might still come before y.
Note you need the Ord constraint to ensure that <= is defined for a.
merge :: Ord a => [a] -> [a] -> [a]
merge xs [] = xs
merge [] ys = ys
merge xs#(x:xs') ys#(y:ys') | x <= y = x : merge xs' ys
| otherwise = y : merge xs ys'
I am trying to implement a very trivial sorting algorithm in Haskell. It compiles but keeps giving me incorrect outputs.
Here is the code
import Data.List
minimum' :: (Ord a) => [a] -> a
minimum' (x:xs) = foldr (\ x y -> if x <= y then x else y) x xs
qsrt :: (Ord a) => [a] -> [a]
qsrt [] = []
qsrt l#(x:xs) = minimum' l : qsrt xs
Any thoughts?
The logic error is that qsrt takes the minimum element of l and then skips x, but x would only be the minimum element of l by accident so you're usually skipping the wrong element.
Just as an addendum to Rein Henrichs's answer, I managed to craft a correct version of the above using a filter.
import Data.List
minimum' :: (Ord a) => [a] -> a
minimum' (x:xs) = foldl' (\ x y -> if x <= y then x else y) x xs
srt :: (Ord a) => [a] -> [a]
srt [] = []
srt l = ml : srt (delete ml l)
where ml = minimum' l
How can I sort list with IO Compare function?
sortWith :: [String] -> (String -> String -> IO Ordering) -> IO [String]
Sortby expects (a->a->Ordering) and I don't know, how to deal with it. I am too lazy to implement quick sort myself.
I'm afraid there is no simple way. If it was possible to lift
sortBy :: Ord a => (a -> a -> Ordering) -> [a] -> [a]
to
sortByM :: (Ord a, Monad m) => (a -> a -> m Ordering) -> [a] -> m [a]
you could see the order of comparisons in implementation of sortBy, violating referential transparency.
In general, it's easy to go from xxxM to xxx but not conversely.
Possible options:
Implement a monadic sorting method
Use the monadlist library, which contains insertion sort (as in dflemstr's answer)
Use unsafePerformIO as a hack
Switch to sorting by key and use the Schwartzian transform
sortOnM :: (Monad m, Ord k) => (a -> m k) -> [a] -> m [a]
sortOnM f xs = liftM (map fst . sortBy (comparing snd)) $
mapM (\x -> liftM (x,) (f x)) xs
The sortBy function uses merge sort as the algorithm in GHC, but the Haskell 98 Report dictates that insertion sort should be used.
For simplicity, because I don't have a compiler so I cannot test my code, I will implement insertion sort here:
import Data.Foldable (foldrM)
insertByM :: (a -> a -> IO Ordering) -> a -> [a] -> IO [a]
insertByM _ x [] = return [x]
insertByM cmp x ys#(y:ys') = do
p <- cmp x y
case p of
GT -> do
rest <- insertByM cmp x ys'
return $ y : rest
_ -> return $ x : ys
sortByM :: (a -> a -> IO Ordering) -> [a] -> IO [a]
sortByM cmp = foldrM (insertByM cmp) []
As I said, I haven't tested this code, but it could/should work.
Oh, I've done this one before! Merge sort with monadic comparator:
type MComparator m a = a -> a -> m Ordering
sortByM :: (Monad m, Functor m) => MComparator m a -> [a] -> m [a]
sortByM cmp [] = return []
sortByM cmp [x] = return [x]
sortByM cmp xs = do
let (ys, zs) = partition xs
ys' <- sortByM cmp ys
zs' <- sortByM cmp zs
merge ys' zs'
where merge [] bs = return bs
merge as [] = return as
merge (a:as) (b:bs) = do
comparison <- cmp a b
case comparison of
LT -> (a:) <$> merge as (b:bs)
_ -> (b:) <$> merge (a:as) bs
partition xs = splitAt (length xs `quot` 2) xs
From my blog post: http://unknownparallel.wordpress.com/2012/07/03/using-monadic-effects-to-reverse-a-merge-sort/
Was it Larry Wall who said that laziness is one of the 3 great virtues of a programmer?
It seems you want to transform a function of type (a -> a -> b) into a function of type (a -> a -> c b). Let's plug that into Hoogle. Now, if you know that IO is a Monad, you'll see about the 10th match down in liftM2. Check the type of (liftM2 sortBy), is that what you want?
I'm a newbie to Haskell, and I'm trying to write an elegant function to merge an arbitrary number of sorted lists into a single sorted list... Can anyone provide an elegant and efficient reference implementation?
Thanks!
Something like this should work:
merge2 pred xs [] = xs
merge2 pred [] ys = ys
merge2 pred (x:xs) (y:ys) =
case pred x y of
True -> x: merge2 pred xs (y:ys)
False -> y: merge2 pred (x:xs) ys
merge pred [] = []
merge pred (x:[]) = x
merge pred (x:xs) = merge2 pred x (merge pred xs)
Here, the function merge2 merges 2 lists. The function merge merges a list of lists. The pred is predicate you use for sorting.
Example:
merge (<) [[1, 3, 9], [2, 3, 4], [7, 11, 15, 22]]
should return
[1,2,3,3,4,7,9,11,15,22]
Since I like taking advantage of infix operators and higher-order functions where it makes sense to, I would write
infixr 5 ##
(##) :: (Ord a) => [a] -> [a] -> [a]
-- if one side is empty, the merges can only possibly go one way
[] ## ys = ys
xs ## [] = xs
-- otherwise, take the smaller of the two heads out, and continue with the rest
(x:xs) ## (y:ys) = case x `compare` y of
LT -> x : xs ## (y:ys)
EQ -> x : xs ## ys
GT -> y : (x:xs) ## ys
-- a n-way merge can be implemented by a repeated 2-way merge
merge :: (Ord a) => [[a]] -> [a]
merge = foldr1 (##)
Here, xs ## ys merges two lists by their natural ordering (and drops duplicates), while merge [xs, ys, zs..] merges any number of lists.
This leads to the very natural definition of the Hamming numbers:
hamming :: (Num a, Ord a) => [a]
hamming = 1 : map (2*) hamming ## map (3*) hamming ## map (5*) hamming
hamming = 1 : merge [map (n*) hamming | n <- [2, 3, 5]] -- alternative
-- this generates, in order, all numbers of the form 2^i * 3^j * 5^k
-- hamming = [1,2,3,4,5,6,8,9,10,12,15,16,18,20,24,25,27,30,32,36,40,45,48,50,..]
Stealing yairchu's unimplemented idea:
{-# LANGUAGE ViewPatterns #-}
import qualified Data.Map as M
import Data.List (foldl', unfoldr)
import Data.Maybe (mapMaybe)
-- merge any number of ordered lists, dropping duplicate elements
merge :: (Ord a) => [[a]] -> [a]
-- create a map of {n: [tails of lists starting with n]}; then
-- repeatedly take the least n and re-insert the tails
merge = unfoldr ((=<<) step . M.minViewWithKey) . foldl' add M.empty where
add m (x:xs) = M.insertWith' (++) x [xs] m; add m _ = m
step ((x, xss), m) = Just (x, foldl' add m xss)
-- merge any number of ordered lists, preserving duplicate elements
mergeDup :: (Ord a) => [[a]] -> [a]
-- create a map of {(n, i): tail of list number i (which starts with n)}; then
-- repeatedly take the least n and re-insert the tail
-- the index i <- [0..] is used to prevent map from losing duplicates
mergeDup = unfoldr step . M.fromList . mapMaybe swap . zip [0..] where
swap (n, (x:xs)) = Just ((x, n), xs); swap _ = Nothing
step (M.minViewWithKey -> Just (((x, n), xs), m)) =
Just (x, case xs of y:ys -> M.insert (y, n) ys m; _ -> m)
step _ = Nothing
where merge, like my original, eliminates duplicates, while mergeDup preserves them (like Igor's answer).
if efficiency wasn't a concern I'd go with
merge = sort . concat
otherwise:
merge :: Ord a => [[a]] -> [a]
merge [] = []
merge lists =
minVal : merge nextLists
where
heads = map head lists
(minVal, minIdx) = minimum $ zip heads [0..]
(pre, ((_:nextOfMin):post)) = splitAt minIdx lists
nextLists =
if null nextOfMin
then pre ++ post
else pre ++ nextOfMin : post
note however that this implementation always linearly searches for the minimum (while for a large number of list one may wish to maintain a heap etc.)
Unlike the other posts, I would have merge :: [a] -> [a] -> [a]
type SortedList a = [a]
merge :: (Ord a) => SortedList a -> SortedList a -> SortedList a
merge [] ys = ys
merge xs [] = xs
merge (x:xs) (y:ys)
| x < y = x : merge xs (y : ys)
| otherwise = y : merge (x : xs) ys
mergeAll :: (Ord a) => [SortedList a] -> SortedList a
mergeAll = foldr merge []
Just a quick note: if you want to have the optimal log n behavior when merging several lists (such as you'd get with a priority queue), you can do it very easily with a tweak to Igor's beautiful solution above. (I would have put this as a comment on his answer above, but I don't have enough reputation.) In particular, you do:
merge2 pred xs [] = xs
merge2 pred [] ys = ys
merge2 pred (x:xs) (y:ys) =
case pred x y of
True -> x: merge2 pred xs (y:ys)
False -> y: merge2 pred (x:xs) ys
everyother [] = []
everyother e0:[] = e0:[]
everyother (e0:e1:es) = e0:everyother es
merge pred [] = []
merge pred (x:[]) = x
merge pred xs = merge2 pred (merge pred . everyother $ xs)
(merge pred . everyother . tail $ xs)
Note that a real priority queue would be a bit faster/more space efficient, but that this solution is asymptotically just as good and, as I say, has the advantage that it's a very minor tweak to Igor's beautifully clear solution above.
Comments?