I'm writing a small Haskell exercise, it is should shift some elements within a list, similar to a Caesar cipher, the code is already working, the code is below.
module Lib (shift, cipherEncode, cipherDecode ) where
import Data.Char
import Data.List
import Data.Maybe
abcdata :: [Char]
abcdata = ['a','b','c','d','e','f','g']
iabcdata :: [Char]
iabcdata = ['g','f','e','d','c','b','a']
shift :: Char -> Int -> Char
shift l n = if (n >= 0)
then normalShift l n
else inverseShift l (abs n)
normalShift :: Char -> Int -> Char
normalShift l n = shifter l n abcdata
inverseShift :: Char -> Int -> Char
inverseShift l n = shifter l n reverse(abcdata) -- This is the line
charIdx :: Char -> [Char] -> Int
charIdx target xs = fromJust $ elemIndex target xs
shifter :: Char -> Int -> [Char] -> Char
shifter l n xs = if (n < length (xs))
then
picker ((charIdx l xs) + n) xs
else
picker ((charIdx l xs) + (n `mod` length (xs))) xs
picker :: Int -> [Char] -> Char
picker n xs = if n < length xs
then
xs!!n
else
xs!!(n `mod` length (xs))
The question I have is regarding the line
inverseShift l n = shifter l n reverse(abcdata)
If I change it by
inverseShift l n = shifter l n iabcdata
it works fine
also, when I do reverse(abcdata) == iabcdata it is True
but when I leave the reverse in the code I get the following error
* Couldn't match expected type `[Char] -> Char'
with actual type `Char'
* The function `shifter' is applied to four arguments,
but its type `Char -> Int -> [Char] -> Char' has only three
In the expression: shifter l n reverse (abcdata)
In an equation for `inverseShift':
inverseShift l n = shifter l n reverse (abcdata)
|
21 | inverseShift l n = shifter l n reverse(abcdata)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* Couldn't match expected type `[Char]'
with actual type `[a0] -> [a0]'
* Probable cause: `reverse' is applied to too few arguments
What am I doing wrong by calling shifter with reverse(abcdata) ?
That's not how parentheses work in Haskell. The way you wrote it, reverse and abcdata would both be arguments to shifter, but you want abcdata to be an argument to reverse. Do shifter l n (reverse abcdata) instead of shifter l n reverse(abcdata).
What am I doing wrong by calling shifter with reverse(abcdata) ?
The answer is in the message:
* Couldn't match expected type `[Char] -> Char'
with actual type `Char'
* The function `shifter' is applied to four arguments,
but its type `Char -> Int -> [Char] -> Char' has only three
In the expression: shifter l n reverse (abcdata)
In an equation for `inverseShift':
inverseShift l n = shifter l n reverse (abcdata)
Repeat,
In an equation for `inverseShift':
inverseShift l n = shifter l n reverse (abcdata)
~~~~~~~~~~~~~ -- mind the gap!
That is how your expression was read by Haskell. And this is how it was written by you:
|
21 | inverseShift l n = shifter l n reverse(abcdata)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
So you haven't in fact called shifter with reverse(abcdata).
You called it with reverse and (abcdata) (as well l and n), as is also explained in the other answer.
Related
I am trying to learn Haskell programming language by trying to figure out some pieces of code.
I have these 2 small functions but I have no idea how to test them on ghci.
What parameters should I use when calling these functions?
total :: (Integer -> Integer) -> Integer -> Integer
total function count = foldr(\x count -> function x + count) 0 [0..count]
The function above is supposed to for the given value n, return f 0 + f 1 + ... + f n.
However when calling the function I don't understand what to put in the f part. n is just an integer, but what is f supposed to be?
iter :: Int -> (a -> a) -> (a -> a)
iter n f
| n > 0 = f . iter (n-1) f
| otherwise = id
iter' :: Int -> (a -> a) -> (a -> a)
iter' n = foldr (.) id . replicate n
This function is supposed to compose the given function f :: a -> a with itself n :: Integer times, e.g., iter 2 f = f . f.
Once again when calling the function I don't understand what to put instead of f as a parameter.
To your first question, you use any value for f such that
f 0 + f 1 + ... + f n
indeed makes sense. You could use any numeric function capable of accepting an Integer argument and returning an Integer value, like (1 +), abs, signum, error "error", (\x -> x^3-x^2+5*x-2), etc.
"Makes sense" here means that the resulting expression has type ("typechecks", in a vernacular), not that it would run without causing an error.
To your second question, any function that returns the same type of value as its argument, like (1+), (2/) etc.
I'm trying to define a simple Haskell function with the type (m -> n -> l) -> (m -> n) -> m -> l.
I thought that it needs be to defined as f g h x = f g (h x), but apparently that's not true. How could I correct this function?
Based on the signature, the only sensical implementation is:
f :: (m -> n -> l) -> (m -> n) -> m -> l
f g h x = g x (h x)
This makes sense since we are given two functions g :: m -> n -> l and h :: m -> n, and a value x :: m. We should construct a value with type l. The only way to do this is to make use of the function g. For the parameter with type m we can work with x, for the second parameter we need a value of type n, we do not have such value, but we can construct one by applying h on x. Since h x has type h x :: n, we thus can use this as second parameter for g.
This function is already defined: it is a special case of (<*>) :: Applicative f => f (n -> l) -> f n -> f l with f ~ (->) m.
Djinn is a tool that reasons about types and thus is generating function definitions based on its signature. If one queries with f :: (m -> n -> l) -> (m -> n) -> m -> l, we get:
f :: (m -> n -> l) -> (m -> n) -> m -> l
f a b c = a c (b c)
which is the same function (except that it uses other variable names).
f :: (m -> n -> l) -> (m -> n) -> m -> l
f g h x = _
Now you need to use the arguments in some way.
g (_ :: m) (_ :: n) :: l
h (_ :: m) :: n
x :: m
Both g and h need a value of type m as their first argument. Well, luckily we have exactly one such value, so it's easy to see what to do.
g x (_ :: n) :: l
h x :: n
x :: m
So now g still needs a value of type n. Again we're lucky, because applying h to x has produced such a value.
g x (h x) :: l
h x :: n
x :: m
Ok, and there we now have something of type l, which is what we needed!
f g h x = g x (h x)
f :: (m -> n -> l) -> (m -> n) -> m -> l
f g h x = l
where
l =
what can produce an l for us? only g:
g
which takes two parameters, an m and an n,
m n
but where can we get those? Well, m we've already got,
m = x
and n we can get from h,
n = h
which needs an m
m
and where do we get an m? We've already got an m!
I was having a look at some list operations and came across !!:
(!!) :: [a] -> Int -> a
xs !! n
| n < 0 = negIndex
| otherwise = foldr (\x r k -> case k of
0 -> x
_ -> r (k-1)) tooLarge xs n
The function (\x r k -> ...) has type a -> (Int -> a) -> Int -> a, but foldr takes a function that should only accept two arguments:
foldr :: (a -> b -> b) -> b -> [a] -> b
foldr k z = go
where
go [] = z
go (y:ys) = y `k` go ys
Can someone explain to me why foldr accepts a function that takes 3 arguments with the following type a -> (Int -> a) -> Int -> a? Especially since the result should have the same type as the second argument?
-> is right-associative. So a -> b -> c is a -> (b -> c). Therefore, your type
a -> (Int -> a) -> Int -> a
is the same as
a -> (Int -> a) -> (Int -> a)
and we can see that it fits foldr's type quite well.
(more explanation for others ;)
(!!) :: [a] -> Int -> a
xs !! n
| n < 0 = negIndex
| otherwise = foldr (\x r k -> case k of
0 -> x
_ -> r (k-1)) tooLarge xs n
foldr :: (a -> b -> b) -> b -> [a] -> b
-- ^1 ^2
foldr commonly makes an accumulated(?) value. In this case, foldr makes an
accumulated function (b) of the type (Int -> a)! foldr ... tooLarge xs is evaluated to an
accumulated function, and this accumulated function (^2) takes an argument n. ^1 is a tooLarge function. Interestingly, the buildup of this
accumulated function depends on the value of a free variable n (i.e., k).
For example, ['a', 'b', 'c'] !! 2 is evaluated like below:
\x r k = \'a' r 2 -> r (2-1) (r is not known yet, and drives further evaluations.)
\x r k = \'b' r 1 -> r (1-1)
\x r k = \'c' r 0 -> 'c'
['a', 'b', 'c'] !! 3 goes like this:
\x r k = \'a' r 3 -> r (3-1)
\x r k = \'b' r 2 -> r (2-1)
\x r k = \'c' r 1 -> r (1-1) (r turns out to be tooLarge.) = tooLarge (1-1) (ERROR!)
You can check debug traces:
module Main where
import Debug.Trace
tooLarge _ = errorWithoutStackTrace "!!!: index too large"
negIndex = errorWithoutStackTrace "!!!: negative index"
(!!!) :: Show a => [a] -> Int -> a
xs !!! n
| n < 0 = negIndex
| otherwise = foldr (\x r k -> trace ("x: " ++ show x ++ ", k: " ++ show k) $
case k of
0 -> x
_ -> r (k-1)) tooLarge xs n
main = do
print $ ['a', 'b', 'c'] !!! 2
print $ ['a', 'b', 'c'] !!! 3
-- x: 'a', k: 2
-- x: 'b', k: 1
-- x: 'c', k: 0
-- 'c'
-- x: 'a', k: 3
-- x: 'b', k: 2
-- x: 'c', k: 1
-- sample: !!!: index too large
This (!!) implementation is a report version. The report version of the prelude is more efficient than a familiar naive recursive implementation,
due to optimizations of foldr.
I want to make a function combine which given two integers n and m, returns a triple of integers
(a, b, gcd(n, m)) such that:
am + bn = gcd(n, m)
Should not assume that the integers will always be positive.
gcd :: Int -> Int -> Int
gcd n m
| n == m = n
| n > m = gcd (n-m) m
| n < m = gcd n (m-n)
combine :: Int ->Int -> (Int,Int,Int)
x1=1; y1=0; x2=0; y2=1
while ( m /=0 )
( q=div n m ; r=mod n m ; n=m ; m=r
t=x2 ; x2=x1-q*x2 ; x1=t
t=y2 ; y2=y1-q*y2 ; y1=t )
combine n m = (x1,y1,gcd(n,m))
You will find a screen capture picture link. Click me---> ![link] http://prikachi.com/images.php?images/238/8749238o.png Please if someone have a solution and have idea what I could replace to create the function, would be much appreciated.
Test for the function: combine 3 2 should give this result => (1,-1,1)
I think you might be looking for something like this:
combine :: Int ->Int -> (Int,Int,Int)
combine n m = (x1, y1, gcd n m) where
(x1, y1) = gcdext n m
gcdext :: Int -> Int -> (Int, Int)
gcdext n m = gcdexthelper n m 1 0 0 1 where
gcdexthelper n m x1 y1 x2 y2
| m == 0 = (x1, y1)
| otherwise = gcdexthelper m r x1p y1p x2p y2p where
q = div n m
r = mod n m
x1p = x2
y1p = y2
x2p = x1 - q * x2
y2p = y1 - q * y2
You can of course implement the same with a while loop, but I believe recursion is much more readable in Haskell, so I used it here.
And by the way, GCD is a standard library function in Haskell, so no need to write your own.
Trying to prove correctness of a insertion function of elements into a bst I got stuck trying to prove a seemingly trivial lemma.
My attempt so far:
Inductive tree : Set :=
| leaf : tree
| node : tree -> nat -> tree -> tree.
Fixpoint In (n : nat) (T : tree) {struct T} : Prop :=
match T with
| leaf => False
| node l v r => In n l \/ v = n \/ In n r
end.
(* all_lte is the proposition that all nodes in tree t
have value at most n *)
Definition all_lte (n : nat) (t : tree) : Prop :=
forall x, In x t -> (x <= n).
Lemma all_lte_trans: forall n m t, n <= m /\ all_lte n t -> all_lte m t.
Proof.
intros.
destruct H.
unfold all_lte in H0.
unfold all_lte.
intros.
Clearly if everything in the tree is smaller than n and n <= m everything is smaller than m, but I cannot seem to make coq believe me. How do I continue?
You have to use the le_trans theorem :
le_trans: forall n m p : nat, n <= m -> m <= p -> n <= p
that comes from Le package.
It meas that you have to import Le or more generally Arith with :
Require Import Arith.
at the beginning of your file. Then, you can do :
eapply le_trans.
eapply H0; trivial.
trivial.