How do i define a Binary instance for Data.Number.BigFloat?
I've defined an instance for LongDouble by writing:
instance Binary LongDouble where
put d = put (decodeFloat d)
get = do
x <- get
y <- get
return $! encodeFloat x y
However trying the following doesn't work:
instance Binary (BigFloat e) where
put d = put (decodeFloat d )
get = do
x <- get
y <- get
return $! encodeFloat x y
GHC gives this error message:
/home/usr/Documents/src/Lib.hs:27:18: error:
• No instance for (Epsilon e) arising from a use of ‘decodeFloat’
Possible fix:
add (Epsilon e) to the context of the instance declaration
• In the first argument of ‘put’, namely ‘(decodeFloat d)’
In the expression: put (decodeFloat d)
In an equation for ‘put’: put d = put (decodeFloat d)
|
27 | put d = put (decodeFloat d )
| ^^^^^^^^^^^^^
/home/usr/Documents/src/Lib.hs:31:19: error:
• No instance for (Epsilon e) arising from a use of ‘encodeFloat’
Possible fix:
add (Epsilon e) to the context of the instance declaration
• In the second argument of ‘($!)’, namely ‘encodeFloat x y’
In a stmt of a 'do' block: return $! encodeFloat x y
In the expression:
do x <- get
y <- get
return $! encodeFloat x y
|
31 | return $! encodeFloat x y
If I provide a specific type for e, such as Prec500, i get this message :
• Illegal instance declaration for ‘Binary (BigFloat Prec500)’
(All instance types must be of the form (T a1 ... an)
where a1 ... an are *distinct type variables*,
and each type variable appears at most once in the instance head.
Use FlexibleInstances if you want to disable this.)
• In the instance declaration for ‘Binary (BigFloat Prec500)’
And using FlexibleInstances compiles, but doesn't result in correctly encoded numbers.
The following also compiles but doesn't encode correctly either:
instance Epsilon e => Binary (BigFloat e) where
put d = put (decodeFloat d )
get = do
x <- get
y <- get
return $! encodeFloat x y
This BigFloat seems to be not super-well-done. The problem lies here:
> floatDigits (0 :: BigFloat Prec500)
-9223372036854775808
(The correct answer should be 500.) I admit I don't fully understand why that is happening; but from the source, the way floatDigits is computed is by taking the log of the precision -- but log is a thing that happens on Doubles and Double doesn't have enough precision to represent 1e-500. So that method of computing the digit count seems doomed from the start.
Why do I say I don't fully understand? Well, I see the following in the source:
floatDigits (BF m _) =
floor $ logBase base $ recip $ fromRational $ precision m
From my reading, fromRational should produce 0 :: Double. But if that were true, the final value would be 0, not minBound:
> floor $ logBase 10 $ recip $ (0 :: Double) :: Int
0
So perhaps there is some dodgy rewriting going on or something.
Anyway, a proper implementation of this type should work differently -- e.g. by having a more informative class than Epsilon that can report the precision as a base and exponent. (Another possible idea would be to have floatRadix return recip precision and floatDigits return 1, but that has some oddities around what should happen if the precision is not the reciprocal of a whole number.)
I am having trouble with this simple code as it is giving me an error stating that there is an incorrect Indention.
opMe x y op = if op =="+" let x+y
main=do
op = "+"
x = 8
y = 10
print(opMe (x, y, op))
The return I am looking for is 18.
The return I have received is Incorrect Indention.
Lots of problems here. Let's fix them one by one:
opMe x y op = if op =="+" let x+y
main=do
op = "+"
x = 8
y = 10
print(opMe (x, y, op))
q58566673.hs:3:1: error:
parse error (possibly incorrect indentation or mismatched brackets)
|
3 | main=do
| ^
The problem here isn't actually indentation. It's that your if statement doesn't have a then or else, so the parser is expecting it to continue, rather than you starting a new declaration. It looks like you used let where you meant to use then, so let's change that. Also, else is mandatory in Haskell. Since you didn't define any other operations yet, I'll use undefined for now, which will let your program compile, but crash if you ever end up there.
opMe x y op = if op =="+" then x+y else undefined
main=do
op = "+"
x = 8
y = 10
print(opMe (x, y, op))
q58566673.hs:3:1: error: parse error on input ‘main’
|
3 | main=do
| ^^^^
Still doesn't work. Ironically, now the problem is indentation, but the new error message no longer mentions that as a possibility. Specifically, the problem is the leading space before opMe. Let's remove that.
opMe x y op = if op =="+" then x+y else undefined
main=do
op = "+"
x = 8
y = 10
print(opMe (x, y, op))
q58566673.hs:4:6: error:
parse error on input ‘=’
Perhaps you need a 'let' in a 'do' block?
e.g. 'let x = 5' instead of 'x = 5'
|
4 | op = "+"
| ^
Here, GHC's suggestion is correct. You need to use let to declare variables in a do block.
opMe x y op = if op =="+" then x+y else undefined
main=do
let op = "+"
let x = 8
let y = 10
print(opMe (x, y, op))
q58566673.hs:5:11: error:
• Ambiguous type variable ‘a0’ arising from the literal ‘8’
prevents the constraint ‘(Num a0)’ from being solved.
Relevant bindings include x :: a0 (bound at q58566673.hs:5:7)
Probable fix: use a type annotation to specify what ‘a0’ should be.
These potential instances exist:
instance Num Integer -- Defined in ‘GHC.Num’
instance Num Double -- Defined in ‘GHC.Float’
instance Num Float -- Defined in ‘GHC.Float’
...plus two others
...plus one instance involving out-of-scope types
(use -fprint-potential-instances to see them all)
• In the expression: 8
In an equation for ‘x’: x = 8
In the expression:
do let op = "+"
let x = 8
let y = 10
print (opMe (x, y, op))
|
5 | let x = 8
| ^
q58566673.hs:6:11: error:
• Ambiguous type variable ‘b0’ arising from the literal ‘10’
prevents the constraint ‘(Num b0)’ from being solved.
Relevant bindings include y :: b0 (bound at q58566673.hs:6:7)
Probable fix: use a type annotation to specify what ‘b0’ should be.
These potential instances exist:
instance Num Integer -- Defined in ‘GHC.Num’
instance Num Double -- Defined in ‘GHC.Float’
instance Num Float -- Defined in ‘GHC.Float’
...plus two others
...plus one instance involving out-of-scope types
(use -fprint-potential-instances to see them all)
• In the expression: 10
In an equation for ‘y’: y = 10
In the expression:
do let op = "+"
let x = 8
let y = 10
print (opMe (x, y, op))
|
6 | let y = 10
| ^^
q58566673.hs:7:3: error:
• No instance for (Show
((a0, b0, [Char]) -> [Char] -> (a0, b0, [Char])))
arising from a use of ‘print’
(maybe you haven't applied a function to enough arguments?)
• In a stmt of a 'do' block: print (opMe (x, y, op))
In the expression:
do let op = "+"
let x = 8
let y = 10
print (opMe (x, y, op))
In an equation for ‘main’:
main
= do let op = ...
let x = ...
let y = ...
....
|
7 | print(opMe (x, y, op))
| ^^^^^^^^^^^^^^^^^^^^^^
q58566673.hs:7:9: error:
• No instance for (Num (a0, b0, [Char]))
arising from a use of ‘opMe’
• In the first argument of ‘print’, namely ‘(opMe (x, y, op))’
In a stmt of a 'do' block: print (opMe (x, y, op))
In the expression:
do let op = "+"
let x = 8
let y = 10
print (opMe (x, y, op))
|
7 | print(opMe (x, y, op))
| ^^^^^^^^^^^^^^^
That's a spectacularly unhelpful set of error messages. The reason these errors are so unhelpful is that they're a type mismatch error, but you didn't specify a type for opMe, so GHC inferred one that was more polymorphic (and thus gives more complicated error messages) than necessary. Let's add a type signature to get a better error message.
opMe :: Integer -> Integer -> String -> Integer
opMe x y op = if op =="+" then x+y else undefined
main=do
let op = "+"
let x = 8
let y = 10
print(opMe (x, y, op))
q58566673.hs:8:14: error:
• Couldn't match expected type ‘Integer’
with actual type ‘(Integer, Integer, [Char])’
• In the first argument of ‘opMe’, namely ‘(x, y, op)’
In the first argument of ‘print’, namely ‘(opMe (x, y, op))’
In a stmt of a 'do' block: print (opMe (x, y, op))
|
8 | print(opMe (x, y, op))
| ^^^^^^^^^^
Much more clear. The problem here is that you defined your function curried (i.e., opMe x y op), but then called it as if it were uncurried (i.e., opMe (x, y, op)). To fix it, pick one or the other and stick to it. Since currying is idiomatic in Haskell, let's go with it:
opMe :: Integer -> Integer -> String -> Integer
opMe x y op = if op =="+" then x+y else undefined
main=do
let op = "+"
let x = 8
let y = 10
print(opMe x y op)
18
And we're done! It works now.
I've written a small program to find the prime factorization of a number. Everything seems to compile except for the main function, which complains about not being able to find a Show1 instance.
{-# LANGUAGE DeriveFunctor #-}
module FactorAnamorphism where
import Data.Functor.Foldable
import Data.List
nextPrimeFactor :: Integer -> Maybe Integer
nextPrimeFactor n = find (\x -> n `mod` x /= 0) [2..(floor $ sqrt $ fromIntegral n)]
data ExprF r = FactorF Integer | MultF r r deriving (Show, Functor)
type Expr = Fix ExprF
factor :: Integer -> Expr
factor = ana coAlg where
coAlg fac = case (nextPrimeFactor fac) of
Just prime -> MultF prime (fac `div` prime)
Nothing -> FactorF fac
main :: IO ()
main = putStrLn $ show $ factor 10
Logs:
% stack build
haskell-playground-0.1.0.0: build (lib + exe)
Preprocessing library haskell-playground-0.1.0.0...
Preprocessing executable 'factor-anamorphism' for
haskell-playground-0.1.0.0...
[1 of 1] Compiling FactorAnamorphism ( app/FactorAnamorphism.hs, .stack-work/dist/x86_64-osx/Cabal-1.24.2.0/build/factor-anamorphism/factor-anamorphism-tmp/FactorAnamorphism.o )
/Users/ian/proj/macalinao/haskell-playground/app/FactorAnamorphism.hs:22:19: error:
• No instance for (Data.Functor.Classes.Show1 ExprF)
arising from a use of ‘show’
• In the second argument of ‘($)’, namely ‘show $ factor 10’
In the expression: putStrLn $ show $ factor 10
In an equation for ‘main’: main = putStrLn $ show $ factor 10
-- While building package haskell-playground-0.1.0.0 using:
/Users/ian/.stack/setup-exe-cache/x86_64-osx/Cabal-simple_mPHDZzAJ_1.24.2.0_ghc-8.0.2 --builddir=.stack-work/dist/x86_64-osx/Cabal-1.24.2.0 build lib:haskell-playground exe:factor-anamorphism exe:haskell-playground-exe --ghc-options " -ddump-hi -ddump-to-file"
Process exited with code: ExitFailure 1
The instance of Show for Fix is: Show1 f => Show (Fix f), which is why the compiler expects Show1 ExprF.
Show1 can be found in base under Data.Functor.Classes, and there is a TH script to derive it in Text.Show.Deriving from deriving-compat.
Im trying to solve this kind of equatin: e^x + sqrt(x) = d, when d is known. It does not have analytic solution so I use variation of binary search to solve it:
helper x = exp x + sqrt x
ex2 c0 c1 x
| abs (h0 - h1) < 10 ^^ (-6) = c0
| hm < x = ex2 m c1 x
| hm >= x = ex2 c0 m x
where h0 = helper c0
h1 = helper c1
m = c0 + (c1 - c0)/2
hm = helper m
This works fine from ghci (c0 and c1 is min and max value for search) but i have problems reading argument x from stdio:
main = do
seed <- getLine
let output = show ex2 0 6 (read seed :: Floating) -- Result is somewhere between helper(0) and helper(6)
in putStrLn output
This breaks my code. It does not compile or load in ghci. I got this error message:
ex2.hs:14:46:
Expecting one more argument to ‘Floating’
Expected a type, but ‘Floating’ has kind ‘* -> Constraint’
In an expression type signature: Floating
In the fourth argument of ‘show’, namely ‘(read seed :: Floating)’
In the expression: show ex2 0 6 (read seed :: Floating)
Can someone explain what it means and how to fix my main function?
There was parentheses missing in let.. line:
Another error: show (ex2 ... (read seed :: Double)) requires parentheses. – chi
I need to define a haskell function:
func :: Int -> Int
func 1 = 1
func 2 = 2
func x = x+1
So that it allows only positive numbers. I've already had a look at a similar question: Non-negative integers
And wrote this:
newtype Positive a = Positive a
toPositive :: (Num a, Ord a) => a -> Positive a
toPositive x
| x < 0 = error "number cannot be negative"
| otherwise = Positive x
func :: Positive a -> a
func (Positive n) = n
Which is however already throwing errors. Thoughts?
Update:
Sample error:
*Main> func 1
<interactive>:32:6:
No instance for (Num (Positive a0)) arising from the literal `1'
Possible fix: add an instance declaration for (Num (Positive a0))
In the first argument of `func', namely `1'
In the expression: func 1
In an equation for `it': it = func 1
*Main>
You forgot to call toPositive to convert an Int to a Positive. Call it this way:
func $ toPositive 1
Also, a quirk of Haskell is its handling of negative number literals. To avoid confusion with the subtraction operator, you must wrap them in parentheses:
func $ toPositive (-1)