Is it possible to have guards on lambda functions?
For example:
\k
| k < 0 -> "negative"
| k == 0 -> "zero"
| otherwise -> "positive"
Other answers show how the extensions LambdaCase and MultiWayIf, introduced since this answer was first written, can solve this. Without them, the nearest direct translation is something a bit like
\k -> case () of
_ | k < 0 -> "negative"
| k == 0 -> "zero"
| otherwise -> "positive"
As of GHC 7.6.1 there is an extension called MultiWayIf that lets you write the following:
\k -> if
| k < 0 -> "negative"
| k == 0 -> "zero"
| otherwise -> "positive"
Which at the very least is more pleasant to look at than the alternative using case.
For pattern-matching, there is a related extension called LambdaCase:
\case
"negative" -> -1
"zero" -> 0
"positive" -> 1
_ -> error "invalid sign"
These extensions are not part of standard Haskell, though, and need to be enabled explicitly via a {-# LANGUAGE LambdaCase #-} or {-# LANGUAGE MultiWayIf #-} pragma at the top of the file, or by compiling with the flag -XLambdaCase or -XMultiWayIf.
I like to keep lambdas short and sweet so as not to break the reader's visual flow. For a function whose definition is syntactically bulky enough to warrant guards, why not stick it in a where clause?
showSign k = mysign ++ " (" ++ show k ++ ")"
where
mysign
| k < 0 = "negative"
| k == 0 = "zero"
| otherwise = "positive"
An elegant and concise way to do it with LambdaCase:
{-# LANGUAGE LambdaCase #-}
\case k | k < 0 -> "negative"
| k == 0 -> "zero"
| otherwise -> "positive"
or
\case
k | k < 0 -> "negative"
| k == 0 -> "zero"
| otherwise -> "positive"
A case when I used it, to catch an EOF error:
{-# LANGUAGE ScopedTypeVariables #-}
o <- hGetContents e `catch` (\case (e :: IOException) | isEOFError e -> return "")
Yet another way uses a combination of the LambdaCase and ViewPatterns GHC extensions:
{-# LANGUAGE LambdaCase, ViewPatterns #-}
\case
((< 0) -> True) -> "negative"
((==0) -> True) -> "zero"
_ -> "positive"
This keeps you from having to name an intermediate variable.
Related
So i am trying to make a recursive factorial function using the case expression and if else although I don't know how to write the <0 condition for my code
factorial x = case of x
<0 -> -1
0 -> 0
.
.
.
I am completely new to Haskell so please don't be too harsh on me.
case takes an arbitrary expression, not just a single variable, so you could write something like
factorial x = case compare x 0 of
LT -> -1
EQ -> 1
GT -> ...
You can work with a guard, for example:
factorial x
| x < 0 = -1
factorial 0 = 0
-- ⋮
or we can add these guards to the case statement, as #Dan D. says:
factorial x = case x of
x | x < 0 -> -1
0 -> 0
-- ⋮
or you can work with view patterns [Haskell gitlab wiki]:
{-# LANGUAGE ViewPatterns #-}
factorial x = case x of
((< 0) -> True) -> -1
0 -> 1
-- ⋮
I am following the Liquid Haskell tutorial:
http://ucsd-progsys.github.io/liquidhaskell-tutorial/04-poly.html
and this example fails:
module Test2 where
import Data.Vector
import Prelude hiding (length)
vectorSum :: Vector Int -> Int
vectorSum vec = go 0 0
where
go acc i
| i < length vec = go (acc + (vec ! i)) (i + 1)
| otherwise = acc
with the following error:
Error: Liquid Type Mismatch
10 | | i < length vec = go (acc + (vec ! i)) (i + 1)
^^^^^^^^^^^^^^^^^
Inferred type
VV : {v : GHC.Types.Int | v == acc + ?b}
not a subtype of Required type
VV : {VV : GHC.Types.Int | VV < acc
&& VV >= 0}
In Context
?b : GHC.Types.Int
acc : GHC.Types.Int
The question is why? The guard (i < length vec) should ensure that (vec ! i) is safe.
This looks like a termination error. Liquid Haskell here seems to assume that acc is the termination metric of go (probably because it's the first Int argument). As such it should always be non-negative and decreasing in each iteration (hence the error message you get).
The way to fix this is providing a correct termination metric, which fulfills the above criteria. Here this would be length vec - i and the corresponding signature for go is:
{-# go :: _ -> i:_ -> _ /[length vec - i] #-}
or something along those lines.
First of all, I don't know which version of LH you were using but I just had the exact same problem. The tutorial states that
LiquidHaskell verifies vectorSum – or, to be precise, the safety of
the vector accesses vec ! i. The verification works out because
LiquidHaskell is able to automatically infer
go :: Int -> {v:Int | 0 <= v && v <= sz} -> Int
which states that the second parameter i is between 0 and the length
of vec (inclusive). LiquidHaskell uses this and the test that i < sz
to establish that i is between 0 and (vlen vec) to prove safety.
They also state that the tutorial is not in accordance with the current version of LiquidHaskell.
It seems that the (refinement-)type inference of LH has changed a bit since the tutorial was written, probably generalizing types more than before, which results in this problem.
The problem is NOT that LH doesn't figure out the guard properly. The problem is that it fails to verify the property 0 <= v.
The following checks fine with version 0.8.6.2 of LH:
{-# LIQUID "--short-names" #-}
{-# LIQUID "--no-termination" #-}
{-# LIQUID "--reflection" #-}
import Prelude hiding (length)
import Data.Vector
{-# go' :: v:Vector Int -> Int -> {i:Int | i>=0 } ->Int #-}
go' :: Vector Int -> Int -> Int -> Int
go' vec acc i
| i < sz = go' vec (acc + (vec ! i)) (i + 1)
| otherwise = acc
where sz = length vec
vecSum :: Vector Int -> Int
vecSum vec = go' vec 0 0
It seems that LH infers thas go is a function in its own right and might be called with an integer smaller than 0 (which it obviously isn't).
I am still playing with that example to convince LH of this fact. If anybody had more success on this please leave a comment.
EDIT:
I found the following paragraph in the same tutorial; It seems that this might have changed:
At the call loop 0 n 0 body the parameters lo and hi are instantiated
with 0 and n respectively, which, by the way is where the inference
engine deduces non-negativity.
How can I define a function with the following signature,
f :: [Int???] -> [Int]
f xs = _ -- what I do with xs doesn't matter for the question
where a is a List of Int's
such that the first argument's inputs, i.e. list elements, must be >= 0, but <= 5 at compile-time?
In other words,
f [6] would fail to compile.
How about:
f :: [Int] -> [Int]
f = filter (\x -> x >= 0 && x <= 5)
Or do you want to enforce the bounds on the type (dependent types)?
If you want to restrict the range of the Int that is allowed you are probably better of using a smart constructor. Have a look here. The idea is that you create your own datatype and your own custom constructor:
newtype Range0_5 = Range0_5 { unRange :: Int }
makeRange0_5 :: Int -> Maybe Range0_5
makeRange0_5 x
| x >= 0 && x <= 5 = Just $ Range0_5 x
| otherwise = Nothing
If you make a smart constructor, it is important to not expose it to the user of the module. This can be done by simply not exporting the Range0_5 constructor.
However this is not a compile time check. Other languages than Haskell might be more appropriate if you really need such a feature.
Since the range is fairly small, you could also make a sum type to represent it:
data Range0_5 = Int0 | Int1 | Int2 | Int3 | Int4 | Int5
If the signature is
f :: [Int] -> [Int]
(which was the original form of the question), then it is impossible to enforce your constraint at compile time. This follows from the standard diagonalization argument of the Halting problem.
Suppose the compiler could detect that
f[g x]
should not compile. By incorporating the source code of the compiler into g, it could choose the opposite of the compiler's decision.
Following your comment on Liquid Haskell (which seems like a very interesting project), note the following:
{-# type Even = {v:Int | v mod 2 = 0} #-}
{-# foo :: n:Even -> {v:Bool | (v <=> (n mod 2 == 0))} #-}
foo :: Int -> Bool
foo n = if n^2 - 1 == (n + 1) * (n - 1) then True else foo (n - 1)
LiquidHaskell claims this function is unsafe, because, potentially foo n calls foo (n - 1). Note, however, that this will never happen: it will only be called if the relationship n2 - 1 ≠ (n + 1) (n - 1), which can never happen.
Again, this is not a criticism of the quality of LiquidHaskell, but rather just pointing out that it, too, cannot solve Halting Problem like issues.
I am currently learning how to write type classes. I can't seem to write the Ord type class with compile errors of ambiguous occurrence.
module Practice where
class (Eq a) => Ord a where
compare :: a -> a -> Ordering
(<), (<=), (>=), (>) :: a -> a -> Bool
max, min :: a -> a -> a
-- Minimal complete definition:
-- (<=) or compare
-- Using compare can be more efficient for complex types.
compare x y
| x == y = EQ
| x <= y = LT
| otherwise = GT
x <= y = compare x y /= GT
x < y = compare x y == LT
x >= y = compare x y /= LT
x > y = compare x y == GT
-- note that (min x y, max x y) = (x,y) or (y,x)
max x y
| x <= y = y
| otherwise = x
min x y
| x <= y = x
| otherwise = y
Errors are
Practice.hs:26:14:
Ambiguous occurrence `<='
It could refer to either `Practice.<=', defined at Practice.hs:5:10
or `Prelude.<=',
imported from `Prelude' at Practice.hs:1:8-15
...
and so on. I think it is clashing with the Prelude defined version.
The problem is that the names of your functions are clashing with the standard ones from the Prelude.
To solve this, you can add an explicit import declaration which hides the conflicting names:
module Practice where
import Prelude hiding (Ord, compare, (<), (<=), (>=), (>), max, min)
...
hammar is right, it's because of clashing with standard Prelude names. But there are another solutions in addition to hiding names from Prelude.
You can import Prelude qualified:
module Practice where
import qualified Prelude as P
...
Next, you can gain access to both you and standard version of function: max will execute your version, and P.max will execute standard Prelude's.
There is also way to completely hide all standard Prelude functions: GHC's extension NoImplicitPrelude (http://www.haskell.org/haskellwiki/No_import_of_Prelude). It can be activated writing
{-# LANGUAGE NoImplicitPrelude #-}
in the very beginning of your file
In F#, I can use | to group cases when pattern matching. For example,
let rec factorial n =
match n with
| 0 | 1 -> 1 // like in this line
| _ -> n * factorial (n - 1)
What's the Haskell syntax for the same?
There is no way of sharing the same right hand side for different patterns. However, you can usually get around this by using guards instead of patterns, for example with elem.
foo x | x `elem` [A, C, G] = ...
| x `elem` [B, D, E] = ...
| otherwise = ...
with guards:
factorial n
| n < 2 = 1
| otherwise = n * (factorial (n - 1))
with pattern matching:
factorial 0 = 1
factorial 1 = 1
factorial n = n * (factorial (n - 1))
I'm not entirely familiar with F#, but in Haskell, case statements allow you to pattern match, binding variables to parts of an expression.
case listExpr of
(x:y:_) -> x+y
[x] -> x
_ -> 0
In the theoretical case that Haskell allowed the same:
It would therefore be problematic to allow multiple bindings
case listExpr of
(x:y:_) | [z] -> erm...which variables are bound? x and y? or z?
There are rare circumstances where it could work, by using the same binding:
unEither :: Either a a -> a
unEither val = case val of
Left v | Right v -> v
And as in the example you gave, it could work alright if you only match literals and do not bind anything:
case expr of
1 | 0 -> foo
_ -> bar
However:
As far as I know, Haskell does not have syntax like that. It does have guards, though, as mentioned by others.
Also note:
Using | in the case statement serves a different function in Haskell. The statement after the | acts as a guard.
case expr of
[x] | x < 2 -> 2
[x] -> 3
_ -> 4
So if this sort of syntax were to be introduced into Haskell, it would have to use something other than |. I would suggest using , (to whomever might feel like adding this to the Haskell spec.)
unEither val = case val of
Left v, Right v -> v
This currently produces "parse error on input ,"
Building on some of the above answers, you can (at least now) use guards to do multiple cases on a single line:
case name of
x | elem x ["Bob","John","Joe"] -> putStrLn "ok!"
"Frank" -> putStrLn "not ok!"
_ -> putStrLn "bad input!"
So, an input of "Bob", "John", or "Joe" would give you an "ok!", whereas "Frank" would be "not ok!", and everything else would be "bad input!"
Here's a fairly literal translation:
factorial n = case n of
0 -> sharedImpl
1 -> sharedImpl
n -> n * factorial (n - 1)
where
sharedImpl = 1
View patterns could also give you a literal translation.
isZeroOrOne n = case n of
0 -> True
1 -> True
_ -> False
factorial1 n = case n of
(isZeroOrOne -> True) -> 1
n -> n * factorial (n - 1)
factorial2 n = case n of
(\n -> case n of { 0 -> True; 1 -> True; _ -> False }) -> 1
n -> n * factorial (n - 1)
Not saying that these are better than the alternatives. Just pointing them out.