So I have a list lets say [t, f, f, t, f] and an infix operator <==>. I want to connect the elements so the end result will look like this t <==> f <==> f <==> t <==> f . The problem that I am having though is that i get this result t <==> (f <==> (f <==> (t <==> f))). I know why this is happening because the resursion returns all previous elements but I have no idea how to fix it.
This is my code:
fun connect(l) =
case l of
x::[] => x
| x::xs => x1 <==> connect(xs);
the end result will look like this t <==> f <==> f <==> t <==> f.
problem is that i get this result t <==> (f <==> (f <==> (t <==> f)))
x <==> y <==> z could mean either (x <==> y) <==> z or x <==> (y <==> z).
If it is a problem that you fold to one side, try folding to the other:
fun connectLeft (x::xs) = foldl (op <==>) x xs
fun connectRight (x::xs) = foldr (op <==>) x xs
You can see how foldl and foldr are implemented.
Or you can see the illustration of folds as structural transformations (Wikipedia).
Edit: Assuming x <==> y <==> z means (x <==> y) && (y <==> z):
fun connect [] = ?
| connect [x] = ?
| connect [x,y] = x <==> y
| connect (x :: y :: rest) =
(x <==> y) && connect (y :: rest)
&& is not the name of SML's built-in logical and-operator, which is called andalso. If x <==> y returns a bool, then perhaps you mean to use andalso here.
Since connect supposedly returns either a bool or some user-defined truthy value, then maybe connect [x] = x, but maybe not.
In any case, connect [] should be considered: Is there a good default here, so that the function does not crash on empty lists?
If you want to write this using list combinators (like map, foldl, etc.) instead of manual recursion, what you can do is:
Convert the input list into a list of pairs, so [x, y, z] becomes [(x, y), (y, z)]. There is an SML function called zip, hiding away in the library ListPair... a few examples that might hint at how to do this:
ListPair.zip [x1,x2,x3] [y1,y2,y3] = [(x1,y1), (x2,y2), (x3,y3)]
ListPair.zip [x1,x2,x3] [x1,x2,x3] = [(x1,x1), (x2,x2), (x3,x3)]
ListPair.zip [x1,x2,x3] [y2,y3] = [(x1,y2), (x2,y3)]
Call map (op <==>) over the list of pairs.
Fold over the result with some && operator.
Related
How can I properly prove that
sequenceA :: (Traversable t, Applicative f) => t (f a) -> f (t a)
sequenceA [] = pure []
sequenceA (x:xs) = pure (:) <*> x <*> sequenceA xs
is essentially the same to monad inputs as
sequenceA' :: Monad m => [m a] -> m [a]
sequenceA' [] = return []
sequenceA' (x:xs) = do
x' <- x
xs' <- sequenceA' xs
return (x':xs')
In spite of the constraint Applicative and Monad of course.
Here's a proof sketch:
Show that
do
x' <- x
xs' <- sequenceA' xs
return (x' : xs')
is equivalent to
do
f1 <- do
cons <- return (:)
x' <- x
return (cons x')
xs' <- sequenceA' xs
return (f1 xs')
This involves desugaring (and resugaring) do notation and applying the Monad laws.
Use the definition of ap:
ap m1 m2 = do { x1 <- m1; x2 <- m2; return (x1 x2) }
to turn the above code into
do
f1 <- return (:) `ap` x
xs' <- sequenceA' xs
return (f1 xs')
and then
return (:) `ap` x `ap` sequenceA' xs
Now you have
sequenceA' [] = return []
sequenceA' (x:xs) = return (:) `ap` x `ap` sequenceA' xs
Assume that pure and <*> are essentially the same as return and `ap`, respectively, and you're done.
This latter property is also stated in the Applicative documentation:
If f is also a Monad, it should satisfy
pure = return
(<*>) = ap
Since the Functor-Applicative-Monad proposal, implemented in GHC 7.10, Applicative is a superclass of Monad. So even though your two functions can't be strictly equivalent, since sequenceA's domain includes sequenceA''s domain, we can look at what happens in this common domain (the Monad typeclass).
This paper shows an interesting demonstration of desugaring do notation to applicative and functor operations (<$>, pure and <*>). If the expressions on the right hand side of your left-pointing arrows (<-) don't depend on each other, as is the case in your question, you can always use applicative operations, and therefore show that your hypothesis is correct (for the Monad domain).
Also have a look at the ApplicativeDo language extension proposal, which contains an example that's just like yours:
do
x <- a
y <- b
return (f x y)
which translates to:
(\x y -> f x y) <$> a <*> b
Substituting f for (:), we get:
do
x <- a
y <- b
return (x : y)
... which translates to...
(\x y -> x : y) <$> a <*> b
--And by eta reduction
(:) <$> a <*> b
--Which is equivalent to the code in your question (albeit more general):
pure (:) <*> a <*> b
Alternatively, you can make GHC's desugarer work for you by using the ApplicativeDo language extension and by following this answer to the SO question "haskell - Desugaring do-notation for Monads". I'll leave this exercise up to you (as it honestly goes beyond my capacities!).
My own two cents
There is no do notation for applicatives in Haskell. It can be seen specifically in this segment.
return and pure do exactly the same, but with different constraints, right?, so this part pure (:) and this part return (x:xs) are essentially the same.
Then, here x <- act you are getting the value of act, and then the value of the recursion xs <- seqn acts, to finally wrap it with the return.
And that's what pure (:) <*> x <*> sequenceA xs is essentially doing.
I have just started learning F*, going through the tutorial. One of the exercises there is to prove that the reverse function on lists is injective.
Since this follows from the fact that involutions are injective I would like to express that fact as a lemma in F*. To do that I define
let is_involutive f = forall x. (f (f x) == x)
let is_injective f = forall x y. (f x == f y) ==> x == y
Is this the right way to define the notion of f being involutive or injective in F*?
Then I state the lemma
val inv_is_inj: #a:eqtype -> a -> f:(a->a) ->
Lemma (requires (is_involutive f)) (ensures(is_injective f))
Informally the proof can be written as
{ fix (x:a) (y:a)
assume (f x == f y)
then have (f (f x) == f (f y))
with (is_involutive f) have (x == y)
} hence (forall (x:a) (y:a). f x == f y ==> x == y)
then have (is_injective f)
How do I express such proof in F*?
In general, what F* language constructs can be used to prove statements of the form forall (x:a). phi x, where phi is a predicate on a type a?
Im making an insertion sort code in SML, here it is
fun compare(x:real, y:real, F) = F(x, y);
fun isEqual(x:real, y:real) = ((x <= y) andalso (x >= y));
fun rinsert(x: real, [], F) = [x]
|rinsert(x, (y::ys), F) =
if isEqual(x, y) then rinsert (x, ys, F)
else if compare(x, y, F) then x::y::ys
else y::(rinsert (x, ys, F));
fun rinsort([], F) = []
|rinsort(x::xs, F) = rinsert(x, (rinsort(xs, F), F));
However, on running it i get this error
val isEqual = fn : real * real -> bool
val rinsert = fn : real * real list * (real * real -> bool) -> real list
stdIn:12.27-12.58 Error: operator and operand don't agree [tycon mismatch]
operator domain: real * real list * (real * real -> bool)
operand: 'Z * ('Y list * 'X)
in expression:
rinsert (x,(rinsort (<exp>,<exp>),F))
I understand that rinsort is calling rinsert incorrectly, but I'm not sure how to fix it.
If it can be useful, This is an example of how your code should work with areal list:
fun compare(x:real, y:real, F) = F x y;
fun isEqual(x:real, y:real) = ((x <= y) andalso (x >= y));
fun rinsert(x: real, [], F) = [x]
|rinsert(x, (y::ys), F) =
if isEqual(x, y) then rinsert (x, ys, F)
else if compare(x, y, F) then x::y::ys
else y::(rinsert (x, ys, F));
fun rinsort([], F) = []
|rinsort(x::xs, F) = rinsert(x, rinsort(xs, F), F);
val funcComp = fn r1 : real => fn r2 : real => if r1 < r2 then true else false;
val l : real list = [1.0, 3.8, 5.6, 3.8, 4.4, 5.6, 6.3, 5.5, 4.6, 8.1];
val b = rinsort(l, funcComp);
Some general feedback:
The function compare only serves the purpose to switch the order of the arguments of F, so you might as well just refer to F itself then.
The function isEqual is kind of bad. Since reals are not equality types in SML for a reason, try and avoid comparing them like that. It turns out, in order to sort reals, you only need <=, not =.
The function rinsert has strict : real type annotations that are unnecessary since your insertion sort, in taking the comparison operator F as a parameter, might as well be generic (polymorphic).
You might want to call the parameter F something more descriptive, like cmp, leq, or whatever reminds you of its purpose.
Here's an example of how one might also make an insertion sort function:
fun sort leq xs =
let fun insert (x, []) = [x]
| insert (x, y::ys) =
if leq (x, y)
then x::y::ys
else y::insert (x, ys)
in List.foldl insert [] xs
end
It has the type ('a * 'a -> bool) -> 'a list -> 'a list. This is comparable to e.g. SML/NJ's built-in ListMergeSort.sort. I've chosen sort to be curried since you might want to specialize it by partial function application, e.g.,
val realsort = sort (op <=) : real list -> real list
val stringsort = sort (op >) : string list -> string list
but I've let the embedded helper function insert to be uncurried since List.foldl takes a function with type ('a * 'b -> 'b), i.e., a tuple of (x, ys) and returns a modified ys with x inserted.
You may want to consider which properties that can test that your function does sort. One property could be that all list elements in the sorted list are in the order specified by the comparison operator leq.
fun sorted_prop _ [] = true
| sorted_prop _ [_] = true
| sorted_prop leq (x::y::xs) = leq (x, y) andalso sorted_prop leq (y::xs)
Another property could be that each element in the unsorted list exists in the sorted list. The latter property may be hard to test if you're not assuming x to have an equality type (''a). But you could do that in the test specifically.
I'm trying to write a Haskell function that automatically distributes a binary operation over a list, kind of how arithmetic operations work in the J language.
You can think of it as a "deep zipWith" that works on nested lists of any depth, including non-lists and lists of different depths.
For example:
distr (+) 1 10 === 11 -- Non-list values are added together
distr (+) [1,2] 10 === [11,12] -- Non-list values distribute over lists
distr (+) [1,2] [10,20] === [11,22] -- Two lists get zipped
distr (+) [[1,2],[3,4]] [[10,20],[30,40]] === [[11,22],[33,44]] -- Nested lists get zipped
Lists of different lengths get truncated, like with zipWith, but this is not important.
Now, I have already written this:
{-# LANGUAGE
MultiParamTypeClasses,
FunctionalDependencies,
UndecidableInstances,
FlexibleInstances
#-}
class Distr a b c x y z | a b c x y -> z
where distr :: (a -> b -> c) -> (x -> y -> z)
instance Distr a b c a b c where distr = id
instance {-# OVERLAPPING #-}
(Distr a b c x y z) => Distr a b c [x] [y] [z]
where distr = zipWith . distr
instance (Distr a b c x y z) => Distr a b c [x] y [z]
where distr f xs y = map (\x -> distr f x y) xs
instance (Distr a b c x y z) => Distr a b c x [y] [z]
where distr f x ys = map (\y -> distr f x y) ys
This defines a 6-parameter typeclass Distr with a function distr :: (Distr a b c x y z) => (a -> b -> c) -> (x -> y -> z), and some instances of Distr on nested lists.
It works well on the examples above, but its behavior on lists of unequal nesting depth is not exactly what I want.
It does this (which works if you add type annotations to (+) and both lists):
distr (+) [[1,2],[3,4]] [10,20] === [[11,12],[23,24]] -- Zip and distribute
Try it here.
What I want is this:
distr (+) [[1,2],[3,4]] [10,20] === [[11,22],[13,24]] -- Distribute and zip
The current implementation applies zipWith until one of its arguments is a non-list value, which is then distributed over the other list.
I would prefer it to distribute one argument (the one with fewer list layers) over the other until it reaches equal nesting depth, and then use zipWith to reduce them to non-list values.
My question is: Can I achieve the second kind of behavior?
I'm happy with a solution that requires me to explicitly tell Haskell the types of the operator and each argument, as my current solution does.
I will not call distr on an operator that takes lists as inputs, so that case need not be handled.
However, I don't want to give extra arguments to distr that serve as type hints, or have several different versions of distr for different use cases.
I know my problem could be solved this way, but I'd prefer a solution where it isn't necessary.
(As a gist in Literate Haskell)
{-# LANGUAGE DataKinds, FlexibleContexts, FlexibleInstances,
TypeFamilies, MultiParamTypeClasses, UndecidableInstances,
RankNTypes, ScopedTypeVariables, FunctionalDependencies, TypeOperators #-}
module Zip where
import Data.Proxy
import GHC.TypeLits
Let's first assume that the two nested lists have the same depth. E.g., depth 2:
zipDeep0 ((+) :: Int -> Int -> Int) [[1,2],[3,4,5]] [[10,20],[30,40]] :: [[Int]]
[[11,22],[33,44]]
Implementation:
zipDeep0
:: forall n a b c x y z
. (ZipDeep0 n a b c x y z, n ~ Levels a x, n ~ Levels b y, n ~ Levels c z)
=> (a -> b -> c) -> (x -> y -> z)
zipDeep0 = zipDeep0_ (Proxy :: Proxy n)
Levels a x computes the depth of a in the nested list type x.
Closed type families allow us to do some non-linear type-level pattern matching
(where a occurs twice in a clause).
type family Levels a x :: Nat where
Levels a a = 0
Levels a [x] = 1 + Levels a x
We use that depth to select the ZipDeep0 instance implementing the zip,
This way is neater than relying only on the six other ordinary type parameters,
as it avoids a problem with type inference and overlapping instances when some list is empty (so
we can't infer its actual type from itself), or when a, b, c are also
list types.
class ZipDeep0 (n :: Nat) a b c x y z where
zipDeep0_ :: proxy n -> (a -> b -> c) -> x -> y -> z
-- Moving the equality constraints into the context helps type inference.
instance {-# OVERLAPPING #-} (a ~ x, b ~ y, c ~ z) => ZipDeep0 0 a b c x y z where
zipDeep0_ _ = id
instance (ZipDeep0 (n - 1) a b c x y z, xs ~ [x], ys ~ [y], zs ~ [z])
=> ZipDeep0 n a b c xs ys zs where
zipDeep0_ _ f = zipWith (zipDeep0_ (Proxy :: Proxy (n - 1)) f)
When the two lists are not of the same depth, let's first assume the second one
is deeper, so we must distribute over it.
We start losing some type inference, we must know at least Levels a x (and
thus a and x) and either Levels b y or Levels c z before this function
can be applied.
Example:
zipDeep1 (+) [10,20 :: Int] [[1,2],[3,4]] :: [[Int]]
[[11,22],[13,24]]
Implementation:
zipDeep1
:: forall n m a b c x y z
. (n ~ Levels a x, m ~ Levels b y, m ~ Levels c z, ZipDeep1 (m - n) a b c x y z)
=> (a -> b -> c) -> x -> y -> z
zipDeep1 = zipDeep1_ (Proxy :: Proxy (m - n))
The difference between levels (m - n) tells us how many layers we must "distribute"
through before falling back to zipDeep0.
class ZipDeep1 (n :: Nat) a b c x y z where
zipDeep1_ :: proxy n -> (a -> b -> c) -> x -> y -> z
instance {-# OVERLAPPING #-} ZipDeep0 (Levels a x) a b c x y z => ZipDeep1 0 a b c x y z where
zipDeep1_ _ = zipDeep0_ (Proxy :: Proxy (Levels a x))
instance (ZipDeep1 (n - 1) a b c x y z, ys ~ [y], zs ~ [z]) => ZipDeep1 n a b c x ys zs where
zipDeep1_ proxy f xs = fmap (zipDeep1_ (Proxy :: Proxy (n - 1)) f xs)
Finally, we can do a type-level comparison when either list may be the deeper
one. We lose all type inference though.
Example:
zipDeep ((+) :: Int -> Int -> Int) [[1,2 :: Int],[3,4]] [10 :: Int,20] :: [[Int]]
[[11,22],[13,24]]
Some type inference is recovered by instead specifying the expected depth of
each list with TypeApplications.
zipDeep #2 #1 ((+) :: Int -> Int -> Int) [[1,2],[3,4]] [10,20]
[[11,22],[13,24]]
Implementation:
zipDeep
:: forall n m a b c x y z
. (ZipDeep2 (CmpNat n m) n m a b c x y z, n ~ Levels a x, m ~ Levels b y)
=> (a -> b -> c) -> x -> y -> z
zipDeep = zipDeep2_ (Proxy :: Proxy '(CmpNat n m, n, m))
class ZipDeep2 (cmp :: Ordering) (n :: Nat) (m :: Nat) a b c x y z where
zipDeep2_ :: proxy '(cmp, n, m) -> (a -> b -> c) -> x -> y -> z
instance {-# OVERLAPPING #-} (n ~ Levels a x, m ~ Levels b y, m ~ Levels c z, ZipDeep1 (m - n) a b c x y z)
=> ZipDeep2 'LT n m a b c x y z where
zipDeep2_ _ = zipDeep1
instance (n ~ Levels a x, m ~ Levels b y, n ~ Levels c z, ZipDeep1 (n - m) b a c y x z)
=> ZipDeep2 cmp n m a b c x y z where
zipDeep2_ _ = flip . zipDeep1 . flip
My homework has been driving me up the wall. I am supposed to write a function called myRepl that takes a pair of values and a list and returns a new list such that each occurrence of the first value of the pair in the list is replaced with the second value.
Example:
ghci> myRepl (2,8) [1,2,3,4]
> [1,8,3,4].
So far I have something like this (but its very rough and not working well at all. I need help with the algorithm:
myRep1 (x,y) (z:zs) =
if null zs then []
else (if x == z then y : myRep1 zs
else myRep1 zs )
I don't know how to create a function that takes a pair of values and a list. I'm not sure what the proper syntax is for that, and I'm not sure how to go about the algorithm.
Any help would be appreciated.
How about something like:
repl (x,y) xs = map (\i -> if i==x then y else i) xs
Explanation
map is a function that takes a function, applies it to each value in the list, and combines all the return values of that function into a new list.
The \i -> notation is a shortcut for writing the full function definition:
-- Look at value i - if it's the same as x, replace it with y, else do nothing
replacerFunc x y i = if x == y then y else i
then we can rewrite the repl function:
repl (x, y) xs = map (replacerFunc x y) xs
I'm afraid the map function you just have to know - it is relatively easy to see how it works. See the docs:
http://www.haskell.org/hoogle/?hoogle=map
How to write this without map? Now, a good rule of thumb is to get the base case of the recursion out of the way first:
myRep1 _ [] = ???
Now you need a special case if the list element is the one you want to replace. I would recommend a guard for this, as it reads much better than if:
myRep1 (x,y) (z:zs)
| x == z = ???
| otherwise = ???
As this is home work, I left a few blanks for you to fill in :-)
myRepl :: Eq a => (a, a) -> [a] -> [a]
myRepl _ [] = []
myRepl (v, r) (x : xs) | x == v = r : myRepl (v, r) xs
| otherwise = x : myRepl (v, r) xs
Untupled arguments, pointfree, in terms of map:
replaceOccs :: Eq a => a -> a -> [a] -> [a]
replaceOccs v r = map (\ x -> if x == v then r else x)