Isabelle’s List theory has set up a syntax translation for filter:
syntax
-- {* Special syntax for filter *}
"_filter" :: "[pttrn, 'a list, bool] => 'a list" ("(1[_<-_./ _])")
translations
"[x<-xs . P]"== "CONST filter (%x. P) xs"
and indeed term "filter (λ x. ¬(P x)) l" will nicely print
"[x←l . ¬ P x]" :: "int list"
But if the expression is simple, e.g. ilter (λ x. P x) l, eta-contraction seems to happen and I get shown
"filter P l" :: "int list"
Can I somehow force the nice syntax (i.e. [x←l . P x]) here as well?
You can avoid eta-contraction by installing an appropriate print_translation. There are several examples for binders and tuples in the HOL sources, e.g., for THE in HOL.thy. They are easy to adapt to filter, for example:
print_translation {*
[(#{const_syntax filter}, fn _ => fn [Abs abs, xs] =>
let val (x, t) = Syntax_Trans.atomic_abs_tr' abs
in Syntax.const #{syntax_const "_filter"} $ x $ t $ xs end)]
*} -- {* To avoid eta-contraction of body *}
Related
Let a pure λ function be a term with nothing but abstractions and applications. On JavaScript, it is possible to infer the source code of a pure function by applying all abstractions to variadic functions that collect their argument list. That is, this is possible:
lambdaSource(function(x){return x(x)}) == "λx.(x x)"
See the code for lambdaSource on this gist. That function became particularly useful for my interests since it allows me to use existing JS engines to normalize untyped lambda calculus expressions much faster than any naive evaluator I could code by myself. Moreover, I know λ-calculus functions can be expressed in Haskell with help of unsafeCoerce:
(let (#) = unsafeCoerce in (\ f x -> (f # (f # (f # x)))))
I do not know how to implement lambdaSource in Haskell because of the lack of variadic functions. Is it possible to infer the normalized source of a pure λ function on Haskell, such that:
lambdaSource (\ f x -> f # (f # (f # x))) == "λ f x . f (f (f x))"
?
Yes, you can, but you need to provide the spine of the type of your function, so it doesn't work for ULC. See also the whole lecture notes.
But as Daniel Wagner says you can just use HOAS.
There is also another opportunity: here is something that looks like HOAS, but is FOAS actually, and all you need is suitable normalization by evaluation (in terms of quote, in terms of reify & reflect). pigworker also wrote a Haskell version of the Jigger, but I can't find it.
We can also do this type-safely in type theory: one way is to use liftable terms (which requires a postulate), or we can reify lambda terms into their PHOAS representation and then convert PHOAS to FOAS (which is very complicated).
EDIT
Here is some HOAS-related code:
{-# LANGUAGE GADTs, FlexibleInstances #-}
infixl 5 #
data Term a = Pure a | Lam (Term a -> Term a) | App (Term a) (Term a)
(#) :: Term a -> Term a -> Term a
Lam f # x = f x
f # x = App f x
instance Show (Term String) where
show = go names where
names = map (:[]) ['a'..'z'] ++ map (++ ['\'']) names
go :: [String] -> Term String -> String
go ns (Pure n) = n
go (n:ns) (Lam f) = concat ["\\", n, " -> ", go ns (f (Pure n))]
go ns (App f x) = concat [go ns f, "(", go ns x, ")"]
k :: Term a
k = Lam $ \x -> Lam $ \y -> x
s :: Term a
s = Lam $ \f -> Lam $ \g -> Lam $ \x -> f # x # (g # x)
omega :: Term a
omega = (Lam $ \f -> f # f) # (Lam $ \f -> f # f)
run t = t :: Term String
main = do
print $ run $ s -- \a -> \b -> \c -> a(c)(b(c))
print $ run $ s # k # k -- \a -> a
-- print $ run $ omega -- bad idea
Also, instead of writing this Lams, #s and stuff, you can parse string representations of lambda terms to HOAS — that's not harder than printing HOAS terms.
Given
notation
rtranclp ("(_^**)" [1000] 1000)
I can write, given an infix op ⇒
"op ⇒⇧*⇧* x x'"
but not the much more readable and prettier
"x ⇒⇧*⇧* x'"
I know that for every concrete relation (⇒ in this case), I can set up an abbreviation for this. But can I also solve this generally, i.e. for any infix relation?
If yes, can I extend that to multiple relations and other arguments? For example, given two infix relations ⇒ and ▹, and another term y I want to set it up so that I can write
x (⇒;▹)⇗y⇖ x'
(note the infix use) instead of
foo op ⇒ op ▹ y x x'
(where, in my case, has type foo :: ('a ⇒ 'a ⇒ bool) ⇒ ('a ⇒ 'b ⇒ bool) ⇒ 'b ⇒ 'a ⇒ 'a).
I believe that a general solution for all infix relations is not possible, because the parser does not know about the relation symbols in isolation. As can be seen from the implementation in mixfix.ML, an infix declaration with relation symbol < is equivalent to two mixfix declarations, namely "op <" and "(_ < _)" with appropriate precedences.
However, there is a more generic and elegant solution than to introduce abbreviations for all combinations of predicates and predicate transformers. First, introduce a syntactic category for relational symbols. To also get the right output, add a syntactic marker _infix
nonterminal rel
syntax (output) "_infix" :: "rel ⇒ logic" ("_")
Then, declare a syntax constant _rtranclp_rel for infix use with infix relations.
syntax "_rtranclp_rel" :: "logic ⇒ rel ⇒ logic ⇒ logic" ("(_ _⇧*⇧* _)")
translations "_rtranclp_rel x R y" ⇀ "CONST rtranclp R x y"
translations "_rtranclp_rel x (_infix R) y" ↽ "CONST rtranclp R x y"
Now, add a syntax translation to your relation rel that you want to use with _rtranclp_rel:
consts rel :: "nat ⇒ nat ⇒ bool" (infix "⇒" 100)
syntax "_rel_infix" :: rel ("⇒")
translations "_rel_infix" ⇀ "CONST rel"
translations "_rel_infix" ↽ "_infix (CONST rel)"
Then, Isabelle should be able to correctly parse and pretty-print x ⇒⇧*⇧* z. Note, however, that all fully applied instances of rtranclp are pretty-printed infix (e.g., rtranclp R x y, independent of whether the relation is an infix symbol.
This mechanism then also works for your function foo:
consts foo :: "('a ⇒ 'a ⇒ bool) ⇒ ('b ⇒ 'b ⇒ bool) ⇒ 'b ⇒ 'a ⇒ 'a ⇒ bool"
syntax "_foo_rel" :: "logic ⇒ rel ⇒ rel ⇒ logic ⇒ logic ⇒ logic" ("_ '(_;_')⇗_⇖ _")
translations "_foo_rel x R S y z" ⇀ "CONST foo R S x y z"
translations "_foo_rel x (_infix R) (_infix S) y z" ↽ "CONST foo R S x y z"
Of course, the precedences in the mixfix annotations should be adjusted to sensible ones. It is even possible to do this recursively. For example:
syntax "_rtranclp_rel2" :: "rel ⇒ rel" ("_⇧*⇧*")
translations "_rtranclp_rel2 R" ⇀ "CONST rtranclp R"
translations "_rtranclp_rel2 (_infix R)" ↽ "_infix (CONST rtranclp R)"
term "x (⇒⇧*⇧*;⇒)⇗y⇖ z"
I am attempting to generate a nice syntax for mapping a function over the values of an associative list, i.e. I want to write [x ↦ f y | (x ↦ y) ∈ l] for mapAList f l. I came up with
syntax
"_alist_map" :: "['b, pttrn, ('a × 'b) list] ⇒ ('a × 'b) list"
("[x ↦ _ | '(x ↦ _') ∈ _]")
which works, but causes term "(x,y)#[]" to tell me Inner syntax error at "(x , y ) # []" and the (x is shaded slightly different.
The reason seems that once x appears in a mixfix annotation, it now always a literal token to the grammer (a delimiter according to §7.4.1 of isar-ref) and no longer an identifier – just like the syntax for if ... then ... else ... prevents if from being a variable name
Can I somehow work around this problem?
Identifier names used in mixfix annotations cannot be used as identifiers any longer, and I don't know any way around that. Therefore, instead of using x as a variable name, you can pick a non-identifier symbol like \<xX> or \<mapAListvariable> and setup the LaTeX output to print this as x by adding \newcommand{\isasymmapAListvariable}{x} to your root.tex.
You can also add \<xX> or \<mapAListvariable> to the symbols file of Isabelle/JEdit (preferably in $ISABELLE_HOME_USER/etc/symbols) and assign it some Unicode point that will be used for display in Isabelle/JEdit.
I just made a small experiment with a function map_alist that hopefully corresponds to your mapAList and which is defined as follows:
fun map_alist :: "('b ⇒ 'c) ⇒ ('a × 'b) list ⇒ ('a × 'c) list"
where
"map_alist f [] = []" |
"map_alist f ((x, y) # xs) = (x, f y) # map_alist f xs"
Then existing syntax can be used which looks a little bit as you intended. Maybe this is an option?
lemma "map_alist f xs = [(x, f y). (x, y) ← xs]"
by (induct xs) auto
i am doing my homework and have an error
I have to do a functions about a data type described now
data RGBdata= RGB Int Int Int
data PBMfile= PBM Int Int [[RGBdata]]
And his show functions
instance Show RGBdata where
show (RGB r g b) = (show r)++" "++(show g)++" "++(show b)
instance Show PBMfile where
show (PBM width height l) = "P3\n"++(show width)++" "++(show height)++"\n255\n"++(foldr (++) "" (map myshow l))
myshow [] = "\n"
myshow (h:t) = (show h)++" "++(myshow t)
And his load and apply function
cargarPBM name = readFile name >>= return . rLines . lines
rLines (_:x:_:xs)= (\[a,b]->(PBM (read a) (read b) (rLines' (read a) (concat $map words xs)))) $ words x
rLines' _ []= []
rLines' a x= (rLine (take (a*3) x): rLines' a (drop (a*3) x))
rLine []= []
rLine (r:g:b:xs)= ((RGB (read r) (read g) (read b)):rLine xs)
aplicar funcion origen destino= cargarPBM origen >>= writeFile destino . show . funcion
When i try to do a function, for example
negative :: PBMfile -> [Int]
negative PBM x y z = [1,2,3]
Hugs error
ERROR file:.\haha.hs:32 - Constructor "PBM" must have exactly 3 arguments in pattern
But PBM x y z are not 3 arguments? What am i doing wrong?
Your function definition negative PBM x y z is trying to pattern match against 4 arguments, the first of which is the PBM data constructor. To actually pattern match the data constructor and its arguments, you should be grouping them, i.e. negative (PBM x y z) = .... The show definition in your question is an example of doing it correctly.
For further reading, try http://en.wikibooks.org/wiki/Haskell/Pattern_matching#The_connection_with_constructors.
You need parentheses,
negative :: PBMfile -> [Int]
negative (PBM x y z) = [1,2,3]
otherwise it is parsed as four arguments to negative.
This is part of a homework assignment so my goal is to understand why this is wrong. As I mentioned before I'm using Moscow ML.
fun filter pred = let
fun f ([], a) = []
| f ([], a) = a
| f (e::L, a) = if pred e then (f L (e::a) ) else (f L a)
in
f
end
The error I get is:
| f (e::L, a) = if pred e then (f L (e::a) ) else (f L a)
^
Type clash: expression of type
'a list cannot have type
'a list * 'b list
I have been reading up on documentation, and it really hasn't helped. What I really don't get is where 'b list is coming from. In our assignment we have to use an accumulator with tail recursion. I believe where my error is is how filter calls the function f. Filter takes the predicate as an argument and f should take the list and accumulator which is initially the empty list.
I've tried calling f like: f L [], But in other examples we didn't actually have to call f with its argument and it was somehow passed automatically.
Anyway, any help understanding where my mistake is and guidance on how to fix the problem would be greatly appreciated.
-aitee
(also if anyone could give me any tips on decoding the type expression errors that could also be very beneficial.)
(f L (e::a)) would work only if f were a curried function, of type 'a list -> 'a list -> 'a list. You should be doing:
if pred e then (f (L, (e::a))) else (f (L,a))
Btw., SMLNJ complains of a redundant match (two f ([], a) clauses are given).
You're confusing tupled versus curried function calls. Your definition of f demands a tuple, (a,b), but you're passing it arguments as f a b. Try replacing your recursive calls to f L ... with f (L,...) instead.
The type error is a little unhelpful, but it's basically saying that you're passing a list when it expects a 2-tuple of lists.