Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

best way to check arguments of a function in haskell

I have a funciton say foo :: [Integer] -> Bool , but it only works if the incoming argument is valid for some criteria, otherwise it should terminate immediately.

 foo x | not $ isSorted x = False
       | otherwise = some_recursive_stuff_here
       where
            isSorted ax = ax == sort ax

etc.

But I don't want to check invariant every time if it is sorted or not. Is there a good way to deal with that other then introducing another internal function?

like image 787
ayan ahmedov Avatar asked Nov 08 '13 22:11

ayan ahmedov


People also ask

How do you check a value in Haskell?

If you are using an interactive Haskell prompt (like GHCi) you can type :t <expression> and that will give you the type of an expression. e.g. or e.g.

What does == mean in Haskell?

The == is an operator for comparing if two things are equal. It is quite normal haskell function with type "Eq a => a -> a -> Bool". The type tells that it works on every type of a value that implements Eq typeclass, so it is kind of overloaded.

How do you pass arguments in Haskell?

You have to pass file1 etc. to runQuery like every other function argument: main = do (file1:file2:file3:_) <- getArgs checkdata command <- getLine runQuery file1 file2 file3 (words command) runQuery file1 file2 file3 ("queryname":parameter1:parameter2) = do ... Well that was simple.

How many arguments does a function have in Haskell?

Every function in Haskell officially only takes one parameter.


1 Answers

You can carry around "proof" that your invariant holds by creating a newtype.

newtype Sorted a = Sorted { fromSorted :: [a] }

sorted :: Ord a => [a] -> Sorted a
sorted = Sorted . sort

foo :: Sorted Integer -> Bool
foo (Sorted as) -> some_recursive_stuff_here

If you hide the Sorted constructor in a separate module then users of your code will be unable to use foo without creating proof of sorting first. They also won't be able to sort a Sorted so you can be sure it's only occurred once.

You can even support proof-maintaining operations if you like.

instance Monoid (Sorted a) where
  mempty = Sorted mempty
  mappend (Sorted as) (Sorted bs) = Sorted (go as bs) where
    -- lazy stable sort
    go :: Ord a => [a] -> [a] -> [a]
    go [] xs = xs
    go xs [] = xs
    go (x:xs) (y:ys) | x == y = x : y : go xs     ys
                     | x <  y = x     : go xs     (y:ys)
                     | x >  y =     y : go (x:xs) ys

(This code is available now on Hackage: http://hackage.haskell.org/package/sorted)

like image 166
J. Abrahamson Avatar answered Sep 30 '22 20:09

J. Abrahamson