foldl definition possible wrong in SML/NJ 110.75 - smlnj

The signature of foldl in SML/NJ 110.75 is
foldl;
val it = fn : ('a * 'b -> 'b) -> 'b -> 'a list -> 'b
Also if I give:
foldl (op -) 2 [1];
I will take as answer ~1 instead of 1
Can you confirm my findings?

From the basis library: http://www.standardml.org/Basis/list.html#SIG:LIST.foldl:VAL
foldl f init [x1, x2, ..., xn]
returns
f(xn,...,f(x2, f(x1, init))...)
or init if the list is empty.
thus in foldl (op -) 2 [1] the result is the evaluation of xn - init or 1 - 2
What makes this particular example a bit harder to understand is that (op -) is a non-associative infix operator. So the f in the basis library definition gets moved between xn and init.
The signature is only for static type checking, and it is worth remembering that 'a and 'b may be of the same type.

Related

Why is foldl signature is a pipeline instead of a tuple like type in SML?

I do not understand why the signature of foldl is like that.
Standard ML of New Jersey v110.79 [built: Tue Aug 8 23:21:20 2017]
- foldl;
val it = fn : ('a * 'b -> 'b) -> 'b -> 'a list -> 'b
In particular, the arrows -> should've been asterisk * like the following:
val it = fn : ('a * 'b -> 'b) * 'b * 'a list -> 'b
And the reason is because foldl takes the following:
Function ('a * 'b -> 'b) that compares & returns one of two strings; assuming acc is 'b, thus, returning acc
acc & 'a list to compare them.
Finally, returning the base 'b which is acc.
* entails it to be a tuple, and which necessitates that all the components of the tuple will have to be provided... -> entails currying, which allows partial application. Both are 2 different semantics.
Also, it is interesting that you write
...foldl takes a function that compares two strings....
foldl is generic and quite polymorphic, so why will it work only with string. A particular function application may work over string data, but not the function definition itself.

SML - Passing NONE or SOME as argument

I have just started on SML and I am having trouble trying to pass NONE/SOME as parameters to a function.
fun fx (SOME x) (SOME y) f = f x y
| fx (SOME x) (NONE) f = NONE
| fx (NONE) (SOME y) f = NONE
| fx (NONE) (NONE) f = NONE;
fun add x y = x + y;
fx (SOME 2) (SOME 4) add;
What I am trying to do is to add two numbers only if neither values are NONE. But I get the following error:
Error: operator and operand do not agree [tycon mismatch]
operator domain: int -> int -> 'Z option
operand: int -> int -> int
in expression:
((fx (SOME 2)) (SOME 4)) add
If remove the cases for NONE, i.e:
fun fx (SOME x) (SOME y) f = f x y
Then it works alright. I don't know where exactly am I making a mistake. f parameter is not optional, yet it is treating as one.
You've already answered the "how", so I will try and explain the "why".
Look at the type of fx in the REPL:
val fx = fn : 'a option -> 'b option -> ('a -> 'b -> 'c option) -> 'c option
It produces a 'c option (it is known from your NONE cases that the result is an option type).
(Note that 'a -> 'b -> 'c option is 'a -> ('b -> ('c option)), not ('a -> 'b -> 'c) option.)
Since your first case is f x y, that must produce an option type - and add doesn't.
This is what the error message is trying to say; since SOME 2 and SOME 4 are int options, fx (SOME 2) (SOME 4) has the type (int -> int -> int option) -> int option (the "operator domain" is int -> int -> int option), but add is an int -> int -> int.
(The use of the word "operator" here is a bit confusing. You get used to it.)
If you want the more generic type 'a option -> 'b option -> ('a -> 'b -> 'c) -> 'c option, you need to wrap the result (as you've found):
fun fx (SOME x) (SOME y) f = SOME (f x y)
Like Nalin pointed out in the comments, I had to redefine the method, just not on add but on fx actually.
fun fx (SOME x) (SOME y) f = SOME (f x y)

Foldleft in Racket

I have a question regarding trying to define a recursively defined foldl function in Racket.
Here is my approach:
(define foldl
(lambda (z c xs)
(match xs
(empty z)
((make-pair x xs) (foldl c (c z x) xs)))))
Unfortunately, when I do this, I get the Error:
expected a function after the open parenthesis but received 1
I cannot quite figure out why this message is popping up. Can someone help me?
The error you are seeing is use to swapping the arguments to foldl.
Your definition is:
(define foldl
(lambda (z c xs)
Here z is an element a c is a constructor.
In
(foldl c (c z x) xs)))))
you swapped the first two argument.
Note: You need to change the match patterns.
Change empty to '().
Change make-pair to cons.

Proper instance for "nested" matching

I have a Lemma of the form FnEquivInner f g implies
outer t (bind t f) === outer t (bind t g) (full example posted below).
I wish to understand what kind of Proper instance I need to write for outer that lets me perform a rewrite in this case, to replace f with g in the call of outer.
In general, how does one write Proper instances where the patterns are non-trivial?
Require Import Setoid.
Require Import Morphisms.
Section PROPERINSTANCE.
Variable T: Type.
Variable inner: T -> (T -> T) -> T.
Variable outer : T -> (T -> T) -> T.
Variable bind: T -> (T -> T) -> (T -> T).
Variable equiv: T -> T -> Prop.
Infix "===" := equiv (at level 50).
Variable equivalence_equiv: Equivalence equiv.
(** Check that equivalence can be found by Coq *)
Lemma check_equiv_refl: forall (t: T), t === t.
reflexivity.
Qed.
Definition FnEquivInner (f g: T -> T): Prop := forall (t: T),
inner t f === inner t g.
(** This is a part of my theory *)
Variable FnEquivOuter:
forall (f g: T -> T)
(t t1: T)
(EQUIVINNER: FnEquivInner f g),
outer t1 (bind t f) === outer t1 (bind t g).
(** This is not a made up example to push coq, I have an actual theorem like this:
* https://github.com/bollu/vellvm/blob/master/src/coq/Memory.v#L923
inner = memEffect
outer = memD
bind = bindM
*)
Lemma useFnEquivOuter:
forall (f g: T -> T)
(t: T)
(EQUIVINNER: FnEquivInner f g),
outer t (bind t f) === outer t (bind t g).
Proof.
intros.
(** What should the Proper instance look like so that if I have a FnEquivInner witness,
I can `rewrite` using it? *)
setoid_rewrite EQUIVINNER.
Qed.
End PROPERINSTANCE.
If you Set Typeclasses Debug. and then try setoid_rewrite EQUIVINNER, and look for the lines that include looking for which come immediately before lines that mention proper_subrelation, you will see
Debug: 1.1-1: looking for (Proper (?R ==> FnEquivInner ==> ?r) bind) with backtracking
Debug: 1.1-1.2-2.1-1: looking for (Proper (?R --> FnEquivInner --> Basics.flip ?r) bind) with backtracking
Debug: 1.3-2.1-1: looking for (Proper (FnEquivInner --> Basics.flip ?r) (bind t)) with backtracking
This is basically a list of the Proper instances you can add to make typeclass resolution for setoid_rewrite go through.
For example, if I write
Global Instance: Proper (eq ==> FnEquivInner ==> eq) bind. Admitted.
then setoid_rewrite goes through.
I assume, though, that you will want something like
Global Instance bind_Proper : Proper (eq ==> FnEquivInner ==> FnEquivInner) bind. Admitted.
If I write this, then setoid_rewrite fails. Let's dig through the typeclass log again, this time looking for where resolution goes wrong after applying bind_Proper. Following the same rule as above, we see that the first line matching the above criterion is
Debug: 2.1-1: looking for (Proper (?R ==> FnEquivInner ==> ?r) outer) with backtracking
If I add
Global Instance outer_Proper: Proper (eq ==> FnEquivInner ==> equiv) outer. Admitted.
then setoid_rewrite again goes through.
Note that you get to fill in ?-prefixed relations (?R, ?r, etc) with any reflexive relation you'd like.
You may ask "why does this black magic work?" The answer is that proper_subrelation is where Coq generally goes wrong. It means, roughly, "I have nothing in my database matching what you're looking for; let me blindly try everything in my database and see if any of them are maybe close enough to work."* (Where "close enough" means "is a subrelation of".) So we look for the places where Coq goes wrong in its search, and we look immediately before that to see what it was looking at. (There are often many steps of partial_application_tactic, which strips arguments off of functions; this is why you only need one Proper instance for bind, rather than one for bind t and another for fun t => bind t f.)
*This is actually useful, sometimes, because eq is a subrelation of every reflexive relation, and so you can get away with not entering relations when you can just use eq. But most of the time, proper_subrelation is not what you want.

Rotate the first argument to a function to become nth

Given a function with at least n arguments, I want to rotate the first argument so that it becomes the nth argument. For example (in untyped lambda calculus):
r(λa. a) = λa. a
r(λa. λb. a b) = λb. λa. a b
r(λa. λb. λc. a b c) = λb. λc. λa. a b c
r(λa. λb. λc. λd. a b c d) = λb. λc. λd. λa. a b c d
And so on.
Can you write r in a generic way? What if you know that n >= 2?
Here's the problem stated in Scala:
trait E
case class Lam(i: E => E) extends E
case class Lit(i: Int) extends E
case class Ap(e: E, e: E) extends E
The rotation should take Lam(a => Lam(b => Lam(c => Ap(Ap(a, b), c)))) and return Lam(b => Lam(c => Lam(a => Ap(Ap(a, b), c)))), for example.
The trick is to tag the "final" value of the functions involved, since to normal haskell, both a -> b and a -> (b->c) are just functions of a single variable.
If we do that, though, we can do this.
{-# LANGUAGE TypeFamilies,FlexibleInstances,FlexibleContexts #-}
module Rotate where
data Result a = Result a
class Rotate f where
type After f
rotate :: f -> After f
instance Rotate (a -> Result b) where
type After (a -> Result b) = a -> Result b
rotate = id
instance Rotate (a -> c) => Rotate (a -> b -> c) where
type After (a -> b -> c) = b -> After (a -> c)
rotate = (rotate .) . flip
Then, to see it in action:
f0 :: Result a
f0 = Result undefined
f1 :: Int -> Result a
f1 = const f0
f2 :: Char -> Int -> Result a
f2 = const f1
f3 :: Float -> Char -> Int -> Result a
f3 = const f2
f1' :: Int -> Result a
f1' = rotate f1
f2' :: Int -> Char -> Result a
f2' = rotate f2
f3' :: Char -> Int -> Float -> Result a
f3' = rotate f3
It's probably impossible without violating the ‘legitimacy’ of HOAS, in the sense that the E => E must be used not just for binding in the object language, but for computation in the meta language. That said, here's a solution in Haskell. It abuses a Literal node to drop in a unique ID for later substitution. Enjoy!
import Control.Monad.State
-- HOAS representation
data Expr = Lam (Expr -> Expr)
| App Expr Expr
| Lit Integer
-- Rotate transformation
rot :: Expr -> Expr
rot e = case e of
Lam f -> descend uniqueID (f (Lit uniqueID))
_ -> e
where uniqueID = 1 + maxLit e
descend :: Integer -> Expr -> Expr
descend i (Lam f) = Lam $ descend i . f
descend i e = Lam $ \a -> replace i a e
replace :: Integer -> Expr -> Expr -> Expr
replace i e (Lam f) = Lam $ replace i e . f
replace i e (App e1 e2) = App (replace i e e1) (replace i e e2)
replace i e (Lit j)
| i == j = e
| otherwise = Lit j
maxLit :: Expr -> Integer
maxLit e = execState (maxLit' e) (-2)
where maxLit' (Lam f) = maxLit' (f (Lit 0))
maxLit' (App e1 e2) = maxLit' e1 >> maxLit' e2
maxLit' (Lit i) = get >>= \k -> when (i > k) (put i)
-- Output
toStr :: Integer -> Expr -> State Integer String
toStr k e = toStr' e
where toStr' (Lit i)
| i >= k = return $ 'x':show i -- variable
| otherwise = return $ show i -- literal
toStr' (App e1 e2) = do
s1 <- toStr' e1
s2 <- toStr' e2
return $ "(" ++ s1 ++ " " ++ s2 ++ ")"
toStr' (Lam f) = do
i <- get
modify (+ 1)
s <- toStr' (f (Lit i))
return $ "\\x" ++ show i ++ " " ++ s
instance Show Expr where
show e = evalState (toStr m e) m
where m = 2 + maxLit e
-- Examples
ex2, ex3, ex4 :: Expr
ex2 = Lam(\a -> Lam(\b -> App a (App b (Lit 3))))
ex3 = Lam(\a -> Lam(\b -> Lam(\c -> App a (App b c))))
ex4 = Lam(\a -> Lam(\b -> Lam(\c -> Lam(\d -> App (App a b) (App c d)))))
check :: Expr -> IO ()
check e = putStrLn(show e ++ " ===> \n" ++ show (rot e) ++ "\n")
main = check ex2 >> check ex3 >> check ex4
with the following result:
\x5 \x6 (x5 (x6 3)) ===>
\x5 \x6 (x6 (x5 3))
\x2 \x3 \x4 (x2 (x3 x4)) ===>
\x2 \x3 \x4 (x4 (x2 x3))
\x2 \x3 \x4 \x5 ((x2 x3) (x4 x5)) ===>
\x2 \x3 \x4 \x5 ((x5 x2) (x3 x4))
(Don't be fooled by the similar-looking variable names. This is the rotation you seek, modulo alpha-conversion.)
Yes, I'm posting another answer. And it still might not be exactly what you're looking for. But I think it might be of use nonetheless. It's in Haskell.
data LExpr = Lambda Char LExpr
| Atom Char
| App LExpr LExpr
instance Show LExpr where
show (Atom c) = [c]
show (App l r) = "(" ++ show l ++ " " ++ show r ++ ")"
show (Lambda c expr) = "(λ" ++ [c] ++ ". " ++ show expr ++ ")"
So here I cooked up a basic algebraic data type for expressing lambda calculus. I added a simple, but effective, custom Show instance.
ghci> App (Lambda 'a' (Atom 'a')) (Atom 'b')
((λa. a) b)
For fun, I threw in a simple reduce method, with helper replace. Warning: not carefully thought out or tested. Do not use for industrial purposes. Cannot handle certain nasty expressions. :P
reduce (App (Lambda c target) expr) = reduce $ replace c (reduce expr) target
reduce v = v
replace c expr av#(Atom v)
| v == c = expr
| otherwise = av
replace c expr ap#(App l r)
= App (replace c expr l) (replace c expr r)
replace c expr lv#(Lambda v e)
| v == c = lv
| otherwise = (Lambda v (replace c expr e))
It seems to work, though that's really just me getting sidetracked. (it in ghci refers to the last value evaluated at the prompt)
ghci> reduce it
b
So now for the fun part, rotate. So I figure I can just peel off the first layer, and if it's a Lambda, great, I'll save the identifier and keep drilling down until I hit a non-Lambda. Then I'll just put the Lambda and identifier right back in at the "last" spot. If it wasn't a Lambda in the first place, then do nothing.
rotate (Lambda c e) = drill e
where drill (Lambda c' e') = Lambda c' (drill e') -- keep drilling
drill e' = Lambda c e' -- hit a non-Lambda, put c back
rotate e = e
Forgive the unimaginative variable names. Sending this through ghci shows good signs:
ghci> Lambda 'a' (Atom 'a')
(λa. a)
ghci> rotate it
(λa. a)
ghci> Lambda 'a' (Lambda 'b' (App (Atom 'a') (Atom 'b')))
(λa. (λb. (a b)))
ghci> rotate it
(λb. (λa. (a b)))
ghci> Lambda 'a' (Lambda 'b' (Lambda 'c' (App (App (Atom 'a') (Atom 'b')) (Atom 'c'))))
(λa. (λb. (λc. ((a b) c))))
ghci> rotate it
(λb. (λc. (λa. ((a b) c))))
One way to do it with template haskell would be like this:
With these two functions:
import Language.Haskell.TH
rotateFunc :: Int -> Exp
rotateFunc n = LamE (map VarP vars) $ foldl1 AppE $ map VarE $ (f:vs) ++ [v]
where vars#(f:v:vs) = map (\i -> mkName $ "x" ++ (show i)) [1..n]
getNumOfParams :: Info -> Int
getNumOfParams (VarI _ (ForallT xs _ _) _ _) = length xs + 1
Then for a function myF with a variable number of parameters you could rotate them this way:
$(return $ rotateFunc $ read $(stringE . show =<< (reify 'myF >>= return . getNumOfParams))) myF
There most certainly are neater ways of doing this with TH, I am very new to it.
OK, thanks to everyone who provided an answer. Here is the solution I ended up going with. Taking advantage of the fact that I know n:
rot :: Int -> [Expr] -> Expr
rot 0 xs = Lam $ \x -> foldl App x (reverse xs)
rot n xs = Lam $ \x -> rot (n - 1) (x : xs)
rot1 n = rot n []
I don't think this can be solved without giving n, since in the lambda calculus, a term's arity can depend on its argument. I.e. there is no definite "last" argument. Changed the question accordingly.
I think you could use the techniques described int the paper An n-ary zipWith in Haskell for this.
Can you write r in a generic way?
What if you know n?
Haskell
Not in plain vanilla Haskell. You'd have to use some deep templating magic that someone else (much wiser than I) will probably post.
In plain Haskell, let's try writing a class.
class Rotatable a where
rotate :: a -> ???
What on earth is the type for rotate? If you can't write its type signature, then you probably need templates to program at the level of generality you are looking for (in Haskell, anyways).
It's easy enough to translate the idea into Haskell functions, though.
r1 f = \a -> f a
r2 f = \b -> \a -> f a b
r3 f = \b -> \c -> \a -> f a b c
etc.
Lisp(s)
Some Lispy languages have the apply function (linked: r5rs), which takes a function and a list, and applies the elements of the list as arguments to the function. I imagine in that case it wouldn't be so hard to just un-rotate the list and send it on its way. I again defer to the gurus for deeper answers.