Hello,
I have made this exercise which can be found at the Craft of Functional Programming book.  exercise 32  Suppose we have to raise 2 to the power n. If n is even, 2*m say, then  2n = 22*m = (2m)2  If n is odd, 2*m+l say, then  2n = 22*m+l = (2n)2*2  Give a recursive function to compute 2n which uses these insights. f2 :: Integer > Integer f2 n  n < 0 = error "This will only run for positive numbers"  n == 0 = 1  even n = f2 ( n `div` 2) ^ 2  odd n = (f2 ( n `div` 2) ^ 2) * 2 Now I have to make Hunit tests for it, But is there a way I can test if the error message is shown when a negative number is being used ? Roelof _______________________________________________ HaskellCafe mailing list [hidden email] http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe 
On Sat, Oct 31, 2015, at 11:16 AM, Roelof Wobben wrote:
> [...] > But is there a way I can test if the error message is shown when a > negative number is being used ? Something like (untested) ``` import qualified Control.Exception as E isErrorCall :: String > a > IO Bool isErrorCall s x = (E.evaluate x >> return False) `E.catch` (\(E.ErrorCall e) > return $ e == s) myTest = isErrorCall "This will only run for positive numbers" . f2 { >> myTest (1) = return True >> myTest 100 = return False } ``` HTH, Joachim _______________________________________________ HaskellCafe mailing list [hidden email] http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe 
In reply to this post by Roelof Wobben
Unfrotunately the answer to this is not simple: http://stackoverflow.com/questions/4243117/howtocatchandignoreacalltotheerrorfunction 'error' more or less terminates the program in an unreasonable way. It would be preferable for f2 to result in a type that can contain the error result to be parsed. Cheers, On Oct 31, 2015 21:16, "Roelof Wobben" <[hidden email]> wrote:
Hello, _______________________________________________ HaskellCafe mailing list [hidden email] http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe 
Op 31102015 om 11:40 schreef Darren Grant:
> > Unfrotunately the answer to this is not simple: > > http://stackoverflow.com/questions/4243117/howtocatchandignoreacalltotheerrorfunction > > 'error' more or less terminates the program in an unreasonable way. > > It would be preferable for f2 to result in a type that can contain the > error result to be parsed. > > Cheers, > Darren > > Oke, So I have to change the type of f2. To what do I have to change it to make it testable. Roelof _______________________________________________ HaskellCafe mailing list [hidden email] http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe 
On Sat, Oct 31, 2015 at 11:46:15AM +0100, Roelof Wobben wrote:
> Op 31102015 om 11:40 schreef Darren Grant: > > > >Unfrotunately the answer to this is not simple: > > > >http://stackoverflow.com/questions/4243117/howtocatchandignoreacalltotheerrorfunction > > > >'error' more or less terminates the program in an unreasonable way. > > > >It would be preferable for f2 to result in a type that can contain > >the error result to be parsed. > > So I have to change the type of f2. > > To what do I have to change it to make it testable. For example, Integer > Maybe Integer _______________________________________________ HaskellCafe mailing list [hidden email] http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe 
In reply to this post by Roelof Wobben
I'd expect most Haskellers to recommend something like, f2 :: Integer > Either Integer ErrorString where ErrorString is some specific error value type. (String may suffice for you.) This is a safe general solution, but there are many potentially more specific possibilities that might make your program simpler depending on how this function relates to the context it will be used in. Cheers, On Oct 31, 2015 21:46, "Roelof Wobben" <[hidden email]> wrote:
Op 31102015 om 11:40 schreef Darren Grant: _______________________________________________ HaskellCafe mailing list [hidden email] http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe 
Small nitpick, but I would generally put the "exception" or "error" in the Left part of an Either and a correct result in the Right part. This has some advantages. 1  Right is right as opposed to wrong. Easy to remember mnemonic. 2  It fits neatly with the Monad (Either e) instance. Roelof, a nice exercise is to first implement your f2 function with the Integer > Maybe Integer type and then with Integer > Either String Integer. If you realize that both Monad Maybe and Monad (Either e) you can use almost the same code. 20151031 12:04 GMT+01:00 Darren Grant <[hidden email]>:
_______________________________________________ HaskellCafe mailing list [hidden email] http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe 
Op 31102015 om 12:10 schreef Roel van
Dijk:
Here my try for the Maybe f2Maybe :: Integer > Maybe Integer f2Maybe n  n > 0 = Nothing  n == 0 = Just 1  even n = Just (f2Maybe ( n `div` 2) ^ 2)  odd n = Just ((f2Maybe ( n `div` 2) ^ 2) * 2) But it will not compile , the clauses for even and odd do not work. Both maybe and either are not explained in the first 4 chapter of the Craft book. Roelof _______________________________________________ HaskellCafe mailing list [hidden email] http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe 
You're very close. Take a look at the even clause: Let (k :: Integer), and consider how the type of the expression producing the error, Just (f2Maybe k) differs from the type of the expression, (f2Maybe k) Cheers, Darren On Sat, Oct 31, 2015 at 11:27 PM, Roelof Wobben <[hidden email]> wrote:
_______________________________________________ HaskellCafe mailing list [hidden email] http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe 
Op 31102015 om 13:44 schreef Darren Grant:
> You're very close. Take a look at the even clause: Let (k :: Integer), > and consider how the type of the expression producing the error, > > Just (f2Maybe k) > > differs from the type of the expression, > > (f2Maybe k) > > Cheers, > Darren > Just (f2Maybe k) is type Maybe (Maybe Integer) f2Maybe k is type Maybe Integer But when I change the code to this : f2Maybe :: Integer > Maybe Integer f2Maybe n  n > 0 = Nothing  n == 0 = Just 1  even n = f2Maybe ( n `div` 2) ^ 2  odd n = (f2Maybe ( n `div` 2) ^ 2) * 2 Then I see this error message : No instance for (Num (Maybe Integer)) arising from a use of ‘^’ In the expression: f2Maybe (n `div` 2) ^ 2 In an equation for ‘f2Maybe’: f2Maybe n  n > 0 = Nothing  n == 0 = Just 1  even n = f2Maybe (n `div` 2) ^ 2  odd n = (f2Maybe (n `div` 2) ^ 2) * 2 Failed, modules loaded: none. No instance for (Num (Maybe Integer)) arising from a use of ‘^’ In the expression: f2Maybe (n `div` 2) ^ 2 In an equation for ‘f2Maybe’: f2Maybe n  n > 0 = Nothing  n == 0 = Just 1  even n = f2Maybe (n `div` 2) ^ 2  odd n = (f2Maybe (n `div` 2) ^ 2) * 2 Failed, modules loaded: none. No instance for (Num (Maybe Integer)) arising from a use of ‘^’ In the expression: f2Maybe (n `div` 2) ^ 2 In an equation for ‘f2Maybe’: f2Maybe n  n > 0 = Nothing  n == 0 = Just 1  even n = f2Maybe (n `div` 2) ^ 2  odd n = (f2Maybe (n `div` 2) ^ 2) * 2 Failed, modules loaded: none. _______________________________________________ HaskellCafe mailing list [hidden email] http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe 
You are even closer now!
What the type checker is trying to tell you is that it doesn't know how to raise Maybe Integer to some power. You apply the ^ operator to two values, f2Maybe (n `div` 2) and 2. Let us give them names: let a = f2Maybe (n `div` 2) :: Maybe Integer b = 2 :: Int in a ^ b You see that the type of a is Maybe Integer. What does this mean? There are only 2 cases to consider. You have Just an integer or you have Nothing. You can use the case construct to write the code for both cases. f2Maybe :: Integer > Maybe Integer f2Maybe n  n > 0 = Nothing  n == 0 = Just 1  even n = case f2Maybe (n `div` 2) of Just x > <fill in> Nothing > <fill in>  odd n = case f2Maybe (n `div` 2) of Just x > <fill in> Nothing > <fill in> _______________________________________________ HaskellCafe mailing list [hidden email] http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe 
In reply to this post by Darren Grant2
I think you misinterpreted that answer. As far as I'm aware, `error`
(except in its type) is no less reasonable than other exceptions, and you can catch it in IO. So as long as you run a test in IO, you can test for the call to `error` (as Joachim showed in another reply). Regards, Erik On 31 October 2015 at 11:40, Darren Grant <[hidden email]> wrote: > Unfrotunately the answer to this is not simple: > > http://stackoverflow.com/questions/4243117/howtocatchandignoreacalltotheerrorfunction > > 'error' more or less terminates the program in an unreasonable way. > > It would be preferable for f2 to result in a type that can contain the error > result to be parsed. > > Cheers, > Darren > > On Oct 31, 2015 21:16, "Roelof Wobben" <[hidden email]> wrote: >> >> Hello, >> >> I have made this exercise which can be found at the Craft of Functional >> Programming book. >> >>  exercise 32 >> >>  Suppose we have to raise 2 to the power n. If n is even, 2*m say, then >>  2n = 22*m = (2m)2 >>  If n is odd, 2*m+l say, then >>  2n = 22*m+l = (2n)2*2 >>  Give a recursive function to compute 2n which uses these insights. >> >> f2 :: Integer > Integer >> f2 n >>  n < 0 = error "This will only run for positive numbers" >>  n == 0 = 1 >>  even n = f2 ( n `div` 2) ^ 2 >>  odd n = (f2 ( n `div` 2) ^ 2) * 2 >> >> >> Now I have to make Hunit tests for it, >> >> But is there a way I can test if the error message is shown when a >> negative number is being used ? >> >> Roelof >> >> _______________________________________________ >> HaskellCafe mailing list >> [hidden email] >> http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe > > > _______________________________________________ > HaskellCafe mailing list > [hidden email] > http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe > HaskellCafe mailing list [hidden email] http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe 
Good clarification. Cheers, On Nov 1, 2015 01:09, "Erik Hesselink" <[hidden email]> wrote:
I think you misinterpreted that answer. As far as I'm aware, `error` _______________________________________________ HaskellCafe mailing list [hidden email] http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe 
The ability to express nontermination is a feature, not a bug. If the
program truly cannot produce a useful result for some input, it should crash, the earlier the better. Wrapping the return value ONLY to make a nontotal program *appear* total is kind of ugly (and commits you to a potentially inappropriate/nonsensical model for the problem at hand). It is cleaner to either constrain the input to values you're prepared to deal with or crash when the implicit invariant is violated. _______________________________________________ HaskellCafe mailing list [hidden email] http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe 
In reply to this post by Roel van Dijk3
Op 31102015 om 14:56 schreef Roel van
Dijk:
Still confusing. with even you can have a integer which will be a integer or nothing if there is a number which is not even. So with 1 it will be Nothing. but will the odd even be reached ? Roelof _______________________________________________ HaskellCafe mailing list [hidden email] http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe 
Op 31102015 om 17:43 schreef Roelof
Wobben:
Solved both ones like this : f2Maybe :: Integer > Maybe Integer f2Maybe n  n < 0 = Nothing  otherwise = Just (f3 n ) f3 :: Integer > Integer f3 n  n == 0 = 1  even n = f3 ( n `div` 2) ^ 2  odd n = (f3 ( n `div` 2) ^ 2) * 2 f2Either :: Integer > Either String Integer f2Either n  n < 0 = Left "This function works only with positive number"  otherwise = Right (f3 n) So I can now test on Nothing or Left "This function works only with positive number" ? Roelof _______________________________________________ HaskellCafe mailing list [hidden email] http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe 
In reply to this post by joachifm
Great points. I often run into situations where sketching out nonterminating endpoints leads to a precise domain, but after peer review it becomes clear that a much simpler program would result from compromising with a less precise domain that eliminates these points altogether. Eliminating branching on constructors in Haskell is a common aspect of this refinement, it's true. Cheers, On Nov 1, 2015 03:18, <[hidden email]> wrote:
The ability to express nontermination is a feature, not a bug. If the _______________________________________________ HaskellCafe mailing list [hidden email] http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe 
In reply to this post by Roelof Wobben
Simplest hack:
f2Maybe :: Integer > Maybe Integer f2Maybe n = if n < 0 then Nothing else Just (g n) where g 0 = 1 g n = if odd n then x*2 else x where x = (g (n `div` 2))^2 There is no need to *keep* checking for a negative number in the recursive code. > > f2Maybe :: Integer > Maybe Integer > f2Maybe n >  n > 0 = Nothing >  n == 0 = Just 1 >  even n = Just (f2Maybe ( n `div` 2) ^ 2) >  odd n = Just ((f2Maybe ( n `div` 2) ^ 2) * 2) Let's try another tack. The recursive calls (f2Maybe (n `div` 2)) give you a value of type Maybe Integer. You want to transform the Integer part. This is an instance of Monad m => m a > (a > b) > m b. There's something almost like that in Control.Monad: liftM :: (a > b) > m a > m b So what you want is liftM (\x > x^2) (f2Maybe (n `div` 2)) liftM (\x > x^2*2) (f2Maybe (n `div` 2)) So f2Maybe n  n < 0 = Nothing f2Maybe 0 = Just 1 f2Maybe n = liftM (if odd n then (\x > x^2*2) else (\x > x^2)) (f2Maybe (n `div` 2)) Or you could use 'do' notation: f2Maybe n  n < 0 = Nothing f2Maybe 0 = Just 1 f2Maybe n = do x < f2Maybe (n `div` 2) return (if odd n then x^2*2 else x^2) Whatever you do, the key thing is that you HAVE a value wrapped up in Just and you need to unwrap it, operate on the value, and rewrap it. So you could do something like rewrap _ Nothing = Nothing rewrap f (Just x) = Just (f x) and then f2Maybe n  n < 0 = Nothing f2Maybe 0 = Just 1 f2Maybe n = rewrap (\x > if odd n then x^2*2 else x^2) (f2Maybe (n `div` 2)) and presto, chango! we've just reinvented liftM under the name 'rewrap'. _______________________________________________ HaskellCafe mailing list [hidden email] http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe 
Administrator

In reply to this post by Roel van Dijk3
On Sat, Oct 31, 2015 at 6:10 PM, Roel van Dijk <[hidden email]> wrote:
I think you're being modest when you call it a "small nitpick." If code can't get Left and Right right, that code immediately becomes very suspicious. Thus, not f2 :: Integer > Either Integer ErrorString but f2 :: Integer > Either ErrorString Integer Nice catch.  KimEe _______________________________________________ HaskellCafe mailing list [hidden email] http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe 
Oops yes! :) On Nov 2, 2015 13:38, "KimEe Yeoh" <[hidden email]> wrote:
_______________________________________________ HaskellCafe mailing list [hidden email] http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe 
Free forum by Nabble  Edit this page 