Is there a difference between these two functions?
ghct says:
Prelude> :t (+1)
(+1) :: Num a => a -> a
Prelude> :t \x->x+1
\x->x+1 :: Num a => a -> a
But
When I used (+1) syntax in this piece of code:
data B = B {
pos :: Int,
cells :: [Int]
} deriving (Show)
createB :: Int -> B
createB n = B 0 (take n $ repeat 0)
size :: B -> Int
size b = length $ cells b
get_curr :: B -> Int
get_curr b = (cells b) !! (pos b)
apply :: (Int -> Int) -> B -> B
apply f b = let n = pos b
h = take n $ cells b -- head
t = drop (n + 1) $ cells b -- tail
in B n $ h ++ [f (get_curr b)] ++ t
-- ...
eval :: [Char] -> StateT B IO ()
eval [] = return ()
eval (x:xs) = do
b <- get
put $ case x of
'+' -> apply (+1) b
'-' -> apply (-1) b
'>' -> fwd b
'<' -> back b
otherwise -> b
-- ...
prelude (as well as compiler) said:
> :load BrainFuck.hs
[1 of 1] Compiling BrainFuck ( BrainFuck.hs, interpreted )
BrainFuck.hs:49:40:
No instance for (Num (Int -> Int))
arising from the literal `1'
Possible fix: add an instance declaration for (Num (Int -> Int))
In the expression: 1
In the first argument of `apply', namely `(- 1)'
In the expression: apply (- 1) b
Failed, modules loaded: none.
What am I doing wrong?
sorry if code is not-so-cool (full source here: https://github.com/nskeip/bf/blob/a755b2d27292593d63fe1e63c2a6e01cebc73520/BrainFuck.hs)
This code:
(-1)
... doesn't mean the same thing as this code:
\ x -> x - 1
- is a special case in Haskell; it is the only prefix operator in the language. When you write (-1), you get "negative one" which is a number, and not "subtract one" which is a function.
You should use subtract 1 to get what you need.
Your problem is not with (+1), it's with (-1):
Prelude> :t (-1)
(-1) :: Num a => a
-1 is a number! Try with apply (\x -> x-1) b or apply (subtract 1) b.
There is no difference between (+1) and \x -> x + 1 and if you look closely, (+1) isn't what's causing your error. (-1) is. And that's because unlike (+1), (-1) is not an operator section, it's negative one.
Instead of subtract the decrement expression can be written directly also as (+(-1)) .
Related
Heyy, I'm Haskell beginner and I pretend to do the following function:
occurrences 3 7 [-1,3,-4,3,4,3,-8,7,7,3]
Output that I want:
(4,2)
I made this try but doesn't worked so well, guess I having troubles to count the elements individually and to return the tuple
occurrences a b [] = 0
occurrences a b (x:xs)
| x == a = 1 + occurrences a b xs
| x == b = 1 + occurrences a b xs
| otherwise = occurrences a b xs
I appreciate any tip and help, thanks ;)
A good approach is to add a type signature, and use the error messages to guide you:
occurrences :: (Eq a) => a -> a -> [a] -> (Int, Int)
occurrences a b [] = 0
occurrences a b (x:xs)
| x == a = 1 + occurrences a b xs
| x == b = 1 + occurrences a b xs
| otherwise = occurrences a b xs
The first error is “Could not deduce (Num (Int, Int)) arising from the literal 0 from the context Eq a”. This means that we can’t use 0 in the first equation because it’s not a tuple, or more precisely, there is no Num instance that allows us to convert from the literal 0 to a tuple via fromIntegral. In the base case, we should return a tuple containing 0 for both sums:
occurrences :: (Eq a) => a -> a -> [a] -> (Int, Int)
occurrences a b [] = (0, 0)
occurrences a b (x:xs)
| x == a = 1 + occurrences a b xs
| x == b = 1 + occurrences a b xs
| otherwise = occurrences a b xs
The next error is “Could not deduce (Num (Int, Int)) arising from a use of + from the context Eq a. This means we’re trying to use + on the result of occurrences, but as with the previous error, it doesn’t have a Num instance to provide +, because it’s now a tuple. The fix here is to match on the result of occurrences and add to the first or second element of the tuple accordingly:
occurrences :: (Eq a) => a -> a -> [a] -> (Int, Int)
occurrences a b [] = (0, 0)
occurrences a b (x:xs)
| x == a = let (m, n) = occurrences a b xs in (m + 1, n)
| x == b = let (m, n) = occurrences a b xs in (m, n + 1)
| otherwise = occurrences a b xs
Now this produces the expected result:
> occurrences 'a' 'b' "ababcb"
(2,3)
But we can improve this solution in a few ways. First, a and b remain the same throughout the computation, so we can do the recursion in a helper function instead of passing a and b around to every call.
occurrences :: (Eq a) => a -> a -> [a] -> (Int, Int)
occurrences a b = go
where
go [] = (0, 0)
go (x:xs)
| x == a = let (m, n) = go xs in (m + 1, n)
| x == b = let (m, n) = go xs in (m, n + 1)
| otherwise = go xs
The idiom here is to define f a b … = go where go = …, and replace calls to f a b … with go—because they’re defined as equal! This is a great example of equational reasoning, replacing one side of an equation with the other.
Finally, since every equation of go except the base case contains a tail call to go, it suggests we can express this pattern of recursion with a fold. Here, our accumulator is the pair of results, and the combining function can increment the results accordingly as we step through the list. Since our accumulator is just a pair of integers, it’s a good idea to use a strict fold (foldl').
import Data.List (foldl')
occurrences :: (Eq a) => a -> a -> [a] -> (Int, Int)
occurrences a b = foldl' go (0, 0)
where
go (m, n) x
| x == a = (m + 1, n)
| x == b = (m, n + 1)
| otherwise = (m, n)
Finally, instead of keeping an accumulator and adding elements one by one, we can just map each element to a value (0 or 1) and reduce them by summation. This map/reduce pattern is captured by foldMap :: (Foldable t, Monoid m) => (a -> m) -> t a -> m, which maps each element of a container (t a) to a value (m) and combines the results using a Monoid instance. The monoid to use here is Sum from Data.Monoid, whose Monoid and Semigroup instances define mempty = Sum 0 and Sum a <> Sum b = Sum (a + b) respectively.
import Data.Coerce (coerce)
import Data.Foldable (foldMap)
import Data.Monoid (Sum(..))
occurrences :: (Eq a) => a -> a -> [a] -> (Int, Int)
occurrences a b = coerce . foldMap go
where
go x
| x == a = (Sum (1 :: Int), mempty)
| x == b = (mempty, Sum (1 :: Int))
| otherwise = mempty
We can make use of functions like first :: Arrow a => a b c -> a (b, d) (c, d) and second :: Arrow a => a b c -> a (d, b) (d, c) to construct a tuple where we apply a function to one of the two items of the 2-tuple. For example:
Prelude Control.Arrow> first (1+) (1,4)
(2,4)
Prelude Control.Arrow> second (1+) (1,4)
(1,5)
We thus can use this to update the tuple with:
import Control.Arrow(first, second)
import Data.List(foldl')
occurrences :: (Eq a, Integral i, Integral j, Foldable f) => a -> a -> f a -> (i, j)
occurrences a b = foldl' (flip f) (0, 0)
where f c | a == c = first (1+)
| b == c = second (1+)
| otherwise = id
For the sample input, this produces:
Prelude Control.Arrow Data.List> occurrences 3 7 [-1,3,-4,3,4,3,-8,7,7,3]
(4,2)
We can easily extent this behavior, by making use of lenses to update one of the elements of tuple.
#emg184 gave a good way to solve this problem, but there could be cleaner, easier to read ways to go about doing this. For example:
occurrences x y xs = (count x xs, count y xs)
where count = (length .) . filter . (==)
count could also be written in a more readable:
count x = (length . filter (== x))
You could approach this problem a lot of different way's here is an example of doing it with a fold.
occurrences :: (Eq a) => a -> a -> [a] -> (Int, Int)
occurrences a b list = foldr (\y (a', b') -> ((isEqual y a a'), (isEqual y b b'))) (0, 0) list
where isEqual listEle tupEle count = if (listEle == tupEle) then (count + 1) else count
One of the problem's is you have a type mismatch. you want a type of:
(Int, Int)
Yet you are returning a type of int here once you have an empty list:
occurrences a b [] = 0 -- Int
occurrences a b (x:xs)
| x == a = 1 + occurrences a b xs
| x == b = 1 + occurrences a b xs
| otherwise = occurrences a b xs
You need some type of an accumulator you could do this by where binding a local function that takes your starting tuple of (0, 0) or you could pass it to occurrences like this:
occurrences :: Int -> Int -> [Int] -> (Int, Int) -> (Int, Int)
I would suggest using a local function since you'll always want to start with (0, 0) in this approach.
occurrences' :: (Eq a) => a -> a -> [a] -> (Int, Int)
occurrences' a b list = go list (0,0)
where go x (e1, e2) = if (x == []) then (e1, e2) else (go (tail x) ((isEqual a (head x) e1), (isEqual b (head x) e2)))
isEqual v v' accum = if (v == v') then (accum + 1) else (accum)
This isnt the most idiomatic way to do it but it shows the point. You should try to use types to help with this.,
Prelude> let [x,y] = [3,4] in x*x+y*y
25
Prelude> let x:[y] = [3,4] in x*x + y*y
25
Prelude> let x:y = 3:4 in x*x+y*y
interactive:6:5: error:
* Non type-variable argument in the constraint: Num [a]
(Use FlexibleContexts to permit this)
* When checking the inferred type
x :: forall a. (Num a, Num [a]) => a
In the expression: let x : y = 3 : 4 in x * x + y * y
In an equation for `it': it = let x : y = 3 : 4 in x * x + y * y
Can someone explain what is happening in the first two statements and why is there an error for the third let ... in .. statement.
In the third example, the right-hand-side of the let assignment is: 3:4. The : (cons) operator has the type signature a -> [a] -> [a]: it takes a value on its left side, and a list of that type of value on the right side. In this case, 3 is an a, but 4 is not a list of a ([a]); it is also an a. This is invalid.
Given the form of your exercise so far, there are two ways that you can fix this expression: with 3:[4] or with 3:4:[].
If you tried running your code now, you would see that it fails on x * x + y * y. This is because your pattern-match assigns x to 3, and y to [4] (a singleton list). A list cannot be multiplied by itself, nor can it be added to a number. So once more, we use the solution for the right-hand-side, on the left-hand-side:
let x:y:[] = 3:4:[]
in x * x + y * y
If we add a few too many type annotations, you can hopefully see where things are going wrong:
-- These work fine
-- let [x, y] = [3, 4] in ...
example1 = let [(x :: a), (y :: a)] :: [a]
= [(3 :: a), (4 :: a)] :: [a]
in x * x + y * y
-- let x:[y] = [3, 4] in ...
example2 = let ((x :: a) : ([(y :: a)] :: [a])) :: [a]
in x * x + y * y
-- This is the incorrect implementation
-- let x:y = 3:4 in ...
example3 :: (Num a) => a
example3 = let (x :: a) : (y :: [a]) -- (:) :: a -> [a] -> [a]
= (3 :: a) : (4 :: a) -- 4 :: a is invalid here: require [a]
in (x :: a) * (x :: a)
+ (y :: [a]) * (y :: [a]) -- Trying to multiply two lists
-- This is the fixed implementation
-- let x:y:[] = 3:4:[] in ...
example3' :: (Num a) => a
example3' = let ((x :: a) : (y :: a) : ([] :: [a])) :: [a]
= ((3 :: a) : (4 :: a) : ([] :: [a])) :: [a]
in x * x + y * y
I have two functions:
firstfunc :: (RandomGen g) => g -> Int -> Float -> [[Int]]
firstfunc rnd n p = makGrid $ map (\t -> if t <= p then 1 else 0) $ take (n*n) (randoms rnd)
where makGrid rnd = unfoldr nextRow (rnd, n)
nextRow (_, 0) = Nothing
nextRow (es, i) = let (rnd, rest) = splitAt n es in Just (rnd, (rest, i-1))
sndfunc firstfunc = head $ do
lst <- firstfunc
return $ map (\x -> if (x == 0) then 2 else x) lst
let newFunc = ((firstfunc .) .) . sndfunc
main = do
gen <- getStdGen
let g = (firstfunc gen 5 0.3)
print g
let h = sndfunc g
print h
print $ newFunc gen 5 0.3
The firstfunc takes two values like 5 and 0.3 and returns a list of lists like: [[0,0,0,1,0],[1,0,0,1,0],[0,0,1,1,0],[0,0,0,0,0],[1,0,0,0,1]]
The sndfunc takes the head of the above list of lists, which is [1,0,0,1,0] from the above example, and replaces the zeroes with 2s like this: [1,2,2,1,2].
Is there a way to combine the two functions such that the firstfunc only returns something like: [[1,2,2,1,2],[0,0,1,1,0],[0,0,0,0,0],[1,0,0,0,1]]?
ERROR:
getting parse error parse error (possibly incorrect indentation or mismatched brackets) on this line: let newFunc = ((firstfunc .) .) . sndfunc
2nd EDIT:
prac.hs:15:32:
Couldn't match type ‘[b]’ with ‘a -> a1 -> b0’
Expected type: [[b]] -> a -> a1 -> b0
Actual type: [[b]] -> [b]
Relevant bindings include
newFunc :: [[b]] -> a -> a1 -> Int -> Float -> [[Int]]
(bound at prac.hs:15:1)
In the second argument of ‘(.)’, namely ‘sndfunc’
In the expression: (((firstfunc .) .) . sndfunc)
Failed, modules loaded: none.
You can either use
print $ sndfunc $ firstfunc gen 5 0.3
or you can define a new function
let newFunc = ((sndfunc .) .) . firstfunc
and use that.
print $ newFunc gen 5 0.3
(the extra (.) operators are needed because firstfunc takes three inputs).
I can't figure it out, Code:
smallSum :: (Ord a, Integral a) => a -> a
smallSum n
| n < 0 = 0
| (n < 20) = n + smallSum (n - 1)
| otherwise = error "Number needs to be in 1..10"
fastSumOfSeriesLength :: (Ord a, Integral a) => a -> a
fastSumOfSeriesLength x
| x < 10 = smallSum x
| x >= 10 = sum (take (rest - 1) [dif !! (firstDigit - 1), dif !! (firstDigit - 1) + 100..]) + smallList !! (firstDigit - 1)
where
smallList = [smallSum x | x <- [1..10]]
largeList = [smallSum x | x <- [11..20]]
dif = [l - s | l <- largeList, s <- smallList]
firstDigit = x `mod` 10
rest = x `div` 10
Error:
ghci> :r
[1 of 1] Compiling Main ( learn.hs, interpreted )
learn.hs:194:32:
Could not deduce (a ~ Int)
from the context (Ord a, Integral a)
bound by the type signature for
fastSumOfSeriesLength :: (Ord a, Integral a) => a -> a
at learn.hs:191:26-54
`a' is a rigid type variable bound by
the type signature for
fastSumOfSeriesLength :: (Ord a, Integral a) => a -> a
at learn.hs:191:26
In the first argument of `(-)', namely `rest'
In the first argument of `take', namely `(rest - 1)'
In the first argument of `sum', namely
`(take
(rest - 1)
[dif !! (firstDigit - 1), dif !! (firstDigit - 1) + 100 .. ])'
Failed, modules loaded: none.
Im looking for someone to point out whats wrong, what it would look light working and what I need to google to learn more about this error.
Check out the types of (!!) and take:
*Main> :t (!!)
(!!) :: [a] -> Int -> a
*Main> :t take
take :: Int -> [a] -> [a]
Since you use these on expressions with the same type as x, this means x must be an Int -- but you declared that this function should work on any kind of (integral) number. (If you read the error slowly, hopefully you will be able to see it saying this.) The simplest fix is to import Data.List and use genericIndex and genericTake instead.
I'm trying to write a prime number generator and utilizing MillerRabin formula check whether or not the number is prime before it returns the number back into me.
Here is my code below:
primegen :: Int -> IO Integer
primegen bits =
fix $ \again -> do
x <- fmap (.|. 1) $ randomRIO (2^(bits - 1), 2^bits - 1)
if primecheck x then return x else again
primesTo100 = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97]
powerMod :: (Integral a, Integral b) => a -> a -> b -> a
powerMod m _ 0 = 1
powerMod m x n | n > 0 = join (flip f (n - 1)) x `rem` m where
f _ 0 y = y
f a d y = g a d where
g b i | even i = g (b*b `rem` m) (i `quot` 2)
| otherwise = f b (i-1) (b*y `rem` m)
witns :: (Num a, Ord a, Random a) => Int -> a -> IO [a]
witns x y = do
g <- newStdGen
let r = [9080191, 4759123141, 2152302898747, 3474749600383, 341550071728321]
fs = [[31,73],[2,7,61],[2,3,5,7,11],[2,3,5,7,11,13],[2,3,5,7,11,13,17]]
if y >= 341550071728321
then return $ take x $ randomRs (2,y-1) g
else return $ snd.head.dropWhile ((<= y).fst) $ zip r fs
primecheck :: Integer -> IO Bool
primecheck n | n `elem` primesTo100 = return True
| otherwise = do
let pn = pred n
e = uncurry (++) . second(take 1) . span even . iterate (`div` 2) $ pn
try = return . all (\a -> let c = map (powerMod n a) e in
pn `elem` c || last c == 1)
witns 100 n >>= try
I don't understand whats going on with the IO Bool. And I'm getting the following error...
Couldn't match expected type `Bool' with actual type `IO Bool'
In the return type of a call of `primecheck'
In the expression: primecheck x
In a stmt of a 'do' block: if primecheck x then return x else again
If I change the IO Bool to just a normal Bool, they will give me this:
Couldn't match expected type `Bool' with actual type `m0 a0'
Thanks for the help guys! I appreciate it.
if primecheck x then return x else again
is not valid because primecheck x returns a value of type IO Bool. You want to sequence the monad with do notation or something like:
primecheck x >>= (\val -> if val then return x else again)
Since primecheck returns IO Bool, when you call it in primegen, you need to sequence it rather than calling it like a pure function.
primegen :: Int -> IO Integer
primegen bits =
fix $ \again -> do
x <- fmap (.|. 1) $ randomRIO (2^(bits - 1), 2^bits - 1)
success <- primecheck x
if success then return x else again