Howto dynamically generate function clauses - macros

I need to dynamically generate function clauses, basing on the user’s config. For the sake of clarity, imagine I have a list of atoms:
#atoms ~w|foo bar baz|a
Coming from, say, config.exs. What I need is to generate this function (the MCVE is oversimplified, but it gives an impression on what I actually need):
#checker fn
{:foo, _} -> false
{:bar, _} -> false
{:baz, _} -> false
_ -> true
end
What I am currently doing is:
#clauses Enum.map(#atoms, fn tag ->
{:->, [], [[{:{}, [], [tag, {:_, [], Elixir}]}], false]}
end) ++ [{:->, [], [[{:_, [], Elixir}], true]}]
defmacrop checker, do: {:fn, [], #clauses}
It works pretty fine, but I expect I am overcomplicating things, missing something simple. So, my question is:
Is there an easy way to generate the function clauses in compile time?

I made it somewhat (see below for more) more readable using quote:
defmodule A do
#atoms ~w|foo bar baz|a
#clauses Enum.flat_map(#atoms, fn tag ->
quote do: ({unquote(tag), _} -> false)
end) ++ quote(do: (_ -> true))
defmacro checker, do: {:fn, [], #clauses}
end
defmodule B do
require A
f = A.checker
IO.inspect f.({:foo, :ok})
IO.inspect f.({:bar, :ok})
IO.inspect f.({:baz, :ok})
IO.inspect f.({:quux, :ok})
end
Output:
false
false
false
true
I expected quote(do: a -> b) to work, but it's a parse error right now so we have to do quote(do: (a -> b)) which wraps the quoted fragment we want in a list.
I also expected unquote to work inside fn when it's inside quote, but that also doesn't.
iex(1)> quote do
...(1)> fn
...(1)> unquote()
...(1)> _ -> true
...(1)> end
...(1)> end
** (SyntaxError) iex:2: expected clauses to be defined with -> inside: 'fn'
I believe these two are either bugs or missing features.

Related

Forcing evaluation of terms before extraction, or other ways to test extracted functions?

In many parts of the standard library, there are a bunch of OCaml-native functions with no Coq counterpart. I implemented a Coq version of some of them (with added proofs to show that the Coq versions behave as I think they ought to), but now how do I check that this actually matches the OCaml version's behavior?
The easiest / most "obvious" way I can think of would be to take a test input x, compute f x in Coq, and extract a comparison f x = [[f x]] (where [[…]] marks evaluation in Coq), then repeat for some number of test cases. Unfortunately, I can't find a way to force evaluation in Coq.
Is there a trick to make this possible? Or is there some other standard way for testing behavior across extraction? (Manually going Compute (f x). and plugging the resulting terms as literals back into the sanity checks would be an ugly fallback… Unfortunately, those won't update automatically when the function is changed, and it would also be a lot of manual work that doesn't exactly encourage exhaustive tests…)
Minimal sample:
Definition foo (b : bool) : bool :=
match b with | true => false | false => true end.
Extract Inlined Constant foo => "not".
Extract Inlined Constant bool_eq => "(=)".
Definition foo_true := foo true.
Definition foo_false := foo false.
Definition foo_test : bool :=
andb (bool_eq (foo true) foo_true) (bool_eq (foo false) foo_false).
Recursive Extraction foo_test.
results in
(** val foo_true : bool **)
let foo_true = not true
(** val foo_false : bool **)
let foo_false = not false
(** val foo_test : bool **)
let foo_test = (&&) ((=) (not true) foo_true) ((=) (not false) foo_false)
which is unhelpful. All the ways I could think of to change the definition of foo_true/foo_false to try and have them pre-evaluated didn't work. I can't find any flag in the extraction mechanism to force evaluation… Both the reference manual's attribute index and the flags/options/tables index didn't contain anything that looks useful. Is there anything that I missed?
Starting a definition with Eval compute in evaluates it before registering the definition.
Definition foo_true := Eval compute in foo true.
Definition foo_false := Eval compute in foo false.
Definition foo_test : bool :=
andb (bool_eq (foo true) foo_true) (bool_eq (foo false) foo_false).
Recursive Extraction foo_test.

Scala's Partial Functions in Haskell

Scala has a very nice support of partial functions, mainly because in Scala when you define a partial function it also defines an isDefinedAt function for it. And also Scala has orElse and andThen functions to work with partial functions.
Haskell does support partial functions by simply non-exhaustively defining a function (though they are strongly discouraged in Haskell community). But to define isDefinedAt function in general you have to use some sort of exception handling, which I'm not being able to figure out. Once isDefinedAt function is defined then it can be used to define orElse and andThen function is already there as (.).
In short, I want to define a function,
isDefinedAt :: (a -> b) -> a -> Bool
isDefinedAt f x = -- returns True if f is defined at x else False
Can anyone please tell me how such a function can be written.
Note, I can define a function with signature
isDefinedAt :: (a -> b) -> a -> IO Bool
for generic b. But I want a function without IO in co-domain.
A nice article on Scala's Partial Functions is - How to create and use partial functions in Scala By Alvin Alexander
I recommend that, like in Scala, you use a separate type for partial functions.
import Control.Arrow
import Data.Maybe
type Partial = Kleisli Maybe
isDefinedAt :: Partial a b -> a -> Bool
isDefinedAt f x = isJust $ runKleisli f x
-- laziness should save some of the work, if possible
orElse :: Partial a b -> Partial a b -> Partial a b
orElse = (<+>)
andThen :: Partial a b -> Partial b c -> Partial a c
andThen = (>>>)
Your versions of isDefinedAt are not what Scala does (even in signature); it's very possible (though discouraged) for a PartialFunction to throw an exception when isDefinedAt is true. Or, when you define one explicitly (not using a literal), vice versa: apply doesn't have to throw when isDefinedAt is false, it's user responsibility not to call it then. So the direct equivalent would just be
data PartialFunction a b = PartialFunction { apply :: a -> b, isDefinedAt :: a -> Boolean }
which isn't particularly useful.
apply and isDefinedAt are only really linked in Scala for PartialFunction literals which requires compiler support:
A PartialFunction's value receives an additional isDefinedAt member, which is derived from the pattern match in the function literal, with each case's body being replaced by true, and an added default (if none was given) that evaluates to false.
You can emulate this by using Template Haskell, I believe, but I honestly think using the more Haskell-like approach as described in Daniel Wagner's answer is better. As he mentions, laziness helps.
Though it works even better if you make sure runKleisli f x is executed only once; optimizing cases where you have both isDefinedAt and runKleisli requires Common Subexpression Elimination, and the compiler is cautious about doing that, see Under what circumstances could Common Subexpression Elimination affect the laziness of a Haskell program?
You could do something like this (DISCLAIMER: I have not checked the laws of the relevant typeclasses, and the presence of a string in the constructor for the exception in Alternative makes me wonder if it is lawful). Scala's heterogeneous andThen is covered by fmap; its homogeneous andThen / compose are covered by the >>> / <<< from Category; orElse is covered by <|>; lift is runToMaybe.
However, without a deep compiler integration such as exists in Scala, the pattern incompleteness warnings will interact poorly with this. Haskell only has module-level pragmas for these things, and you won't want to just indiscriminately turn them off in any module where you declare inexhaustive functions, or you may get nasty surprises. Depending on your usecase, you may find optics more idiomatic and less problematic; you can have the boilerplate generated for you through Template Haskell.
(Note: I called it Inexhaustive because PartialFunction is something of a misnomer, in that it implies that Function is total. But Scala has no termination or positivity checkers, so the compiler is not actually able to talk about totality; so you get this weird situation where a function that is not a partial function is just a "regular" Function, whereas you should be able to call it a "total Function". The question here is not partially or totality, which is a broader idea, but inexhaustivity of pattern matches.)
{-# LANGUAGE TypeApplications #-}
module Inexhaustive
( Inexhaustive, inexhaustive
, runToMaybe, isDefinedAt
) where
import Prelude hiding ((.), id)
import Control.Applicative
import Control.Exception
import Control.Category
import Data.Maybe
import System.IO.Unsafe (unsafePerformIO)
newtype Inexhaustive a b = Inexhaustive (a -> b)
inexhaustive :: (a -> b) -> Inexhaustive a b
inexhaustive = Inexhaustive
runToMaybe :: Inexhaustive a b -> a -> Maybe b
runToMaybe (Inexhaustive f) x =
let io = fmap Just $ evaluate $ f x
in unsafePerformIO $ catch #PatternMatchFail io (\_ -> return Nothing)
isDefinedAt :: Inexhaustive a b -> a -> Bool
isDefinedAt f = isJust . runToMaybe f
instance Functor (Inexhaustive z) where
fmap f (Inexhaustive g) = inexhaustive (f . g)
instance Applicative (Inexhaustive z) where
pure x = inexhaustive (const x)
(Inexhaustive zab) <*> (Inexhaustive za) = Inexhaustive (\z -> zab z $ za z)
instance Alternative (Inexhaustive z) where
empty = inexhaustive (\_ -> throw $ PatternMatchFail "inexhaustive empty")
f <|> g =
inexhaustive $ \x ->
case runToMaybe f x <|> runToMaybe g x of
Just y -> y
instance Category Inexhaustive where
id = inexhaustive id
(Inexhaustive f) . (Inexhaustive g) = Inexhaustive (f . g)

Using guards in Elixir macros

I am working on macro which would take a function and add some additional functionality. Eg.:
This:
defstate this_works(a, b) do
a + b + 1
end
Should be converted to this:
def this_works(a, b) do
IO.puts("LOGGING whatever")
a + b + 1
end
This is what I have so far. Try running this piece of code in iex:
defmodule MyMacro do
defmacro defstate(ast, do: block) do
{fn_atom, _} = Macro.decompose_call(ast)
quote do
def unquote(fn_atom)(var!(a), var!(b)) do
IO.puts("LOGGING")
unquote(block)
end
end
end
end
defmodule Test1 do
import MyMacro
defstate this_works(a, b) do
a + b + 1
end
end
Test.this_works(1, 2)
This works as expected.
Now, this module does not compile:
defmodule Test2 do
import MyMacro
defstate this_fails(a, b)
when 1 < 2
when 2 < 3
when 3 < 4 do
a + b + 1
end
end
The only change is that I added a guard and macro is unable to deal with that.
How can I improve MyMacro.defstate to make it work with a function with any number of guards?
If you inspect fn_atom with the defstate this_fails(a, b) when 1 < 2, you'll see that it's :when instead of :this_fails. This is because of how when expressions are represented in the Elixir AST:
iex(1)> quote do
...(1)> def foo, do: 1
...(1)> end
{:def, [context: Elixir, import: Kernel],
[{:foo, [context: Elixir], Elixir}, [do: 1]]}
iex(2)> quote do
...(2)> def foo when 1 < 2, do: 1
...(2)> end
{:def, [context: Elixir, import: Kernel],
[{:when, [context: Elixir],
[{:foo, [], Elixir}, {:<, [context: Elixir, import: Kernel], [1, 2]}]},
[do: 1]]}
You can fix this using some pattern matching:
defmodule MyMacro do
defmacro defstate(ast, do: block) do
f = case ast do
{:when, _, [{f, _, _} | _]} -> f
{f, _, _} -> f
end
quote do
def unquote(ast) do
IO.puts("LOGGING #{unquote(f)}")
unquote(block)
end
end
end
end
defmodule Test do
import MyMacro
defstate this_works(a, b) do
a + b + 1
end
defstate this_works_too(a, b) when a < 2 do
a + b + 1
end
end
defmodule A do
def main do
IO.inspect Test.this_works(1, 2)
IO.inspect Test.this_works_too(1, 2)
IO.inspect Test.this_works_too(3, 2)
end
end
A.main
Output:
LOGGING this_works
4
LOGGING this_works_too
4
** (FunctionClauseError) no function clause matching in Test.this_works_too/2
The following arguments were given to Test.this_works_too/2:
# 1
3
# 2
2
a.exs:24: Test.this_works_too/2
a.exs:33: A.main/0
(elixir) lib/code.ex:376: Code.require_file/2
(I also changed the unquote after def to make sure the when clause is preserved.)
The call to defstate is expanded at compile time to the things in the quote block from your defmacro. As such, guard expressions will not be applied to the macro call directly, because at compile time, the function you're defining inside is not called.
So you have to grab the :when tuple yourself and add the guards yourself:
defmodule MyMacro do
defmacro defstate({:when, _, [ast, guards]}, do: block) do
{fn_atom, _} = Macro.decompose_call(ast)
quote do
def unquote(fn_atom)(var!(a), var!(b)) when unquote(guards) do
IO.puts("LOGGING")
unquote(block)
end
end
end
end
Note how I match for a {:when, _, [ast, guards]} tuple now.
When you call a macro with a guard, it will put the original ast inside the first item of the arguments list, and the guard expression inside the second item.
Note that you'll still have to define a catch-all macro definition below this one in case you want to use your macro without guard clauses.

How to convert partial functions to safe(Maybe) functions?

I want it to use library-defined partialfunc more convenient, or write callback with partial pattern-matching.
like this,
partialMaybe :: forall a b. (Partial => a -> b) -> a -> Maybe b
I couldn't find similar in some major libraries.
How to define it? or already defined in libs?
data ABC a = A a | B a | C a
f1 = someHigherOrderFunc $ partialMaybe \(A a) -> someFunc a -- if not 'A', return Nothing.
-- same as
f2 = someHigherOrderFunc $ case _ of A a -> Just $ someFunc a
_ -> Nothing -- requires line break, seems syntax redundant...
using: purescript 0.11.6
Edit:
I did it...
partialMaybe :: forall a b. (Partial => a -> b) -> a -> Maybe b
partialMaybe f a = runPure $ catchException (const $ pure Nothing) (Just <<< unsafePartial f <$> pure a)
this is...umm...very ugly. it's not.
'Failed pattern match' exception is thrown by the purescript.
so I think it should be able to handle by purescript.
Can't do it?
If you want an exception if a case is missed, use Partial. If you want otherwise, use Maybe or Either or another appropriate sum type.
You can catch the exception thrown from a failed pattern match. There is no way for a failed pattern match to not throw an exception.

How to concisely express function iteration?

Is there a concise, idiomatic way how to express function iteration? That is, given a number n and a function f :: a -> a, I'd like to express \x -> f(...(f(x))...) where f is applied n-times.
Of course, I could make my own, recursive function for that, but I'd be interested if there is a way to express it shortly using existing tools or libraries.
So far, I have these ideas:
\n f x -> foldr (const f) x [1..n]
\n -> appEndo . mconcat . replicate n . Endo
but they all use intermediate lists, and aren't very concise.
The shortest one I found so far uses semigroups:
\n f -> appEndo . times1p (n - 1) . Endo,
but it works only for positive numbers (not for 0).
Primarily I'm focused on solutions in Haskell, but I'd be also interested in Scala solutions or even other functional languages.
Because Haskell is influenced by mathematics so much, the definition from the Wikipedia page you've linked to almost directly translates to the language.
Just check this out:
Now in Haskell:
iterateF 0 _ = id
iterateF n f = f . iterateF (n - 1) f
Pretty neat, huh?
So what is this? It's a typical recursion pattern. And how do Haskellers usually treat that? We treat that with folds! So after refactoring we end up with the following translation:
iterateF :: Int -> (a -> a) -> (a -> a)
iterateF n f = foldr (.) id (replicate n f)
or point-free, if you prefer:
iterateF :: Int -> (a -> a) -> (a -> a)
iterateF n = foldr (.) id . replicate n
As you see, there is no notion of the subject function's arguments both in the Wikipedia definition and in the solutions presented here. It is a function on another function, i.e. the subject function is being treated as a value. This is a higher level approach to a problem than implementation involving arguments of the subject function.
Now, concerning your worries about the intermediate lists. From the source code perspective this solution turns out to be very similar to a Scala solution posted by #jmcejuela, but there's a key difference that GHC optimizer throws away the intermediate list entirely, turning the function into a simple recursive loop over the subject function. I don't think it could be optimized any better.
To comfortably inspect the intermediate compiler results for yourself, I recommend to use ghc-core.
In Scala:
Function chain Seq.fill(n)(f)
See scaladoc for Function. Lazy version: Function chain Stream.fill(n)(f)
Although this is not as concise as jmcejuela's answer (which I prefer), there is another way in scala to express such a function without the Function module. It also works when n = 0.
def iterate[T](f: T=>T, n: Int) = (x: T) => (1 to n).foldLeft(x)((res, n) => f(res))
To overcome the creation of a list, one can use explicit recursion, which in reverse requires more static typing.
def iterate[T](f: T=>T, n: Int): T=>T = (x: T) => (if(n == 0) x else iterate(f, n-1)(f(x)))
There is an equivalent solution using pattern matching like the solution in Haskell:
def iterate[T](f: T=>T, n: Int): T=>T = (x: T) => n match {
case 0 => x
case _ => iterate(f, n-1)(f(x))
}
Finally, I prefer the short way of writing it in Caml, where there is no need to define the types of the variables at all.
let iterate f n x = match n with 0->x | n->iterate f (n-1) x;;
let f5 = iterate f 5 in ...
I like pigworker's/tauli's ideas the best, but since they only gave it as a comments, I'm making a CW answer out of it.
\n f x -> iterate f x !! n
or
\n f -> (!! n) . iterate f
perhaps even:
\n -> ((!! n) .) . iterate