Elm: How do you log a function body? - elm

If I log a function:
Debug.log "List.foldl" (toString List.foldl)
<function> : a -> a
I get its function signature. How do I get the body of the function?

Debug.log takes two arguments: string and any variable. Both of them will be printed out and first paramenter should be used as a simple description what you are sending to logs.
In your case it could be:
Debug.log "List.foldl func" <| List.foldl
<function>
: (a -> b -> b) -> b -> List a -> b

Related

Printf arguments in OCaml

In OCaml, I obtain an error I do not understand when passing arguments which should work to Printf.printf. It is probably because I do not understand that function completely, but I cannot pin down what does not work.
First, I define a function (used for logging):
utop # let log verbosity level str =
if level <= verbosity then (
Printf.printf "\nLevel %i: " level;
Printf.printf str);;
val log : int -> int -> (unit, out_channel, unit) format -> unit = <fun>
All seems well, but then I obtain this:
utop # log 0 0 "%i" 0;;
Error: This function has type
int -> int -> (unit, out_channel, unit) format -> unit
It is applied to too many arguments; maybe you forgot a `;'.
although the following works:
utop # Printf.printf;;
- : ('a, out_channel, unit) format -> 'a = <fun>
utop # Printf.printf "%i" 0;;
0- : unit = ()
So, how can I define a function which does what log intends to do ?
Edit: Indeed, log 0 0 "%i" 0;; looks like too many arguments (4 instead of 3), but so does Printf.printf "%i" 0;; (2 instead of 1), and it works. With partial application, this gives this:
utop # Printf.printf "%i";;
- : int -> unit = <fun>
utop # log 0 0 "%i";;
Error: This expression has type (unit, unit) CamlinternalFormatBasics.precision
but an expression was expected of type
(unit, int -> 'a) CamlinternalFormatBasics.precision
Type unit is not compatible with type int -> 'a
The printf-like functions are variadic, in the sense that they accept a variable number of arguments. It is not really specific to printf and the family, you can define your own variadic functions in OCaml, this is fully supported by the type system. The only magic of printf is that the compiler translates a string literal, e.g., "foo %d to a value of type format.
Now, let's look at the type of the printf function,
('a, out_channel, unit) format -> 'a
Notice that it returns 'a which is a type variable. Since 'a could be anything it could be also a function. The ('a, out_channel, unit) format is the type of the format string that defines the type of function that is generated by this format string. It is important to understand though, that despite that "foo %d" looks like a string, in fact, it is a special built-in value of type _ format, which has a literal that looks like a string (though not all valid strings are valid literals for the _ format type.
Just to demonstrate that the first argument of printf is not a string, let's try the following,
# Printf.printf ("foo " ^ "%d");;
Line 1, characters 14-29:
1 | Printf.printf ("foo " ^ "%d");;
^^^^^^^^^^^^^^^
Error: This expression has type string but an expression was expected of type
('a, out_channel, unit) format
Now, when we know that printf is not a typical function, let's define a printf-like function ourselves. For that we need to use the kprintf-family of functions, e.g.,
# #show Printf.ksprintf;;
val ksprintf : (string -> 'd) -> ('a, unit, string, 'd) format4 -> 'a
This function takes the function which receives the resulting string which we can log, for example,
# let log fmt = Printf.ksprintf (fun s -> print_endline ("log> "^s)) fmt;;
val log : ('a, unit, string, unit) format4 -> 'a = <fun>
# log "foo";;
log> foo
- : unit = ()
This resulting function looks more like sprintf, i.e., it will play nicely with pretty-printing function that work with string as their output devices (this is a different topic). You may find it more easier to define your logging functions, using either Printf.kfprintf or, much better, using Format.kasprintf or Format.kfprintf. The latter two functions have the following types,
val kasprintf : (string -> 'a) -> ('b, formatter, unit, 'a) format4 -> 'b
val kfprintf : (formatter -> 'a) -> formatter ->
('b, formatter, unit, 'a) format4 -> 'b
But the type of format works with the formatter type (which is an abstraction of the output device) that is the type that the pretty printers (conventionally named pp) are accepting. So the log function defined using the Format module will play better with the existing libraries.
So, using Format.kasprintf we can define your log function as,
# let log verbosity level =
Format.kasprintf (fun msg ->
if level <= verbosity then
Format.printf "Level %d: %s#\n%!" level msg);;
val log : int -> int -> ('a, Format.formatter, unit, unit) format4 -> 'a = <fun>
And here is how it could be used,
# log 0 0 "Hello, %s, %d times" "world" 3;;
Level 0: Hello, world, 3 times
- : unit = ()

Trying to bring implicit argument into scope on the left side of a definition in Idris results in "is f applied to too many arguments" error

The function applyRule is supposed to extract the implicit argument n that is used in another arguments it gets, of type VVect.
data IVect : Vect n ix -> (ix -> Type) -> Type where -- n is here
Nil : IVect Nil b
(::) : b i -> IVect is b -> IVect (i :: is) b
VVect : Vect n Nat -> Type -> Type -- also here
VVect is a = IVect is (flip Vect a)
-- just for completeness
data Expression = Sigma Nat Expression
applyRule : (signals : VVect is Double) ->
(params : List Double) ->
(sigmas : List Double) ->
(rule : Expression) ->
Double
applyRule {n} signals params sigmas (Sigma k expr1) = cast n
Without referring to {n}, the code type-checks (if cast n is changed to some valid double). Adding it in, however, results in the following error:
When checking left hand side of applyRule:
Type mismatch between
Double (Type of applyRule signals params sigmas rule)
and
_ -> _ (Is applyRule signals
params
sigmas
rule applied to too many arguments?)
This doesn't seem to make sense to me, because I'm not pattern-matching on any parameter that could have a dependency on n, so I thought that simply putting it in curly braces would bring it into scope.
You can only bring n into scope if it is defined somewhere (e.g. as a variable in the arguments). Otherwise it would be hard to figure out where the n comes from – at least for a human.
applyRule : {is : Vect n Nat} ->
(signals : VVect is Double) ->
(params : List Double) ->
(sigmas : List Double) ->
(rule : Expression) ->
Double
applyRule {n} signals params sigmas (Sigma k expr1) = cast n

How do you print a List in Elm?

How do I convert a value of type List to a String in Elm?
Basically I'm looking for a function with the signature a -> String or List -> String.
Example
Let's say I have a function intAverage:
intAverage l = case l of
[] -> 0
otherwise -> Debug.log (<<SHOW_FUNCTION>> l) (List.sum l // List.length l)
Here I want to inspect the list, in order to understand what's being passed to my function. Debug.log expects a String which makes me look for a function with the signature a -> String or List -> String but I have been unsuccessful in finding such a function in the Elm package docs.
Haskell has Debug.traceShow (which is simply an application of the function show on the first argument of Debug.trace) but I can't find the equivalent in Elm.
Edit: This is no longer true as of Elm version 0.19. See the other answer to this question.
The toString was what I was looking for, but couldn't find.
toString :: a -> String
I found it in the Basics-package: toString documentation
On Elm 0.19, it's been moved to Debug.toString:
For example:
> Debug.toString [1,2,3]
"[1,2,3]" : String

Unsolved metavariable for function that has no inhabited arguments

I am getting an unsolved metavariable for foo in the code below:
namespace Funs
data Funs : Type -> Type where
Nil : Funs a
(::) : {b : Type} -> (a -> List b) -> Funs (List a) -> Funs (List a)
data FunPtr : Funs a -> Type -> Type where
here : FunPtr ((::) {b} _ bs) b
there : FunPtr bs b -> FunPtr (_ :: bs) b
total foo : FunPtr [] b -> Void
How do I convince Idris that foo has no valid patterns to match on?
I've tried adding
foo f = ?foo
and then doing a case split in Emacs on f (just to see what might come up), but that just removes the line, leaving foo as an unsolved meta.
It turns out all I need to do is enumerate all possible patterns for foo's argument, and then Idris is able to figure out, one by one, that they are un-unifyable with foo's type:
foo : FunPtr [] b -> Void
foo here impossible
foo (there _) impossible

Testing QuickCheck properties against multiple types?

I have a type class Atomic, which defines functions for converting certain types to/from a wrapper value (Atom). I'd like to define a QuickCheck property which states: "for all instances of Atomic, any value may be stored and retrieved safely". The property looks like this:
class Atomic a where
toAtom :: a -> Atom
fromAtom :: Atom -> Maybe a
prop_AtomIdentity x = fromAtom (toAtom x) == Just x
However, if I just try to run that property through QuickCheck, it just picks one instance (Bool) and tests it. I'm currently working around that by defining type signatures for each supported atomic type in the test list, but this is verbose and error-prone:
containerTests =
[ run (prop_AtomIdentity :: Bool -> Bool)
, run (prop_AtomIdentity :: Word8 -> Bool)
, run (prop_AtomIdentity :: String -> Bool)
{- etc -} ]
I'm trying to define a function which will do this automatically:
forallAtoms :: (Atomic a, Show a) => (a -> Bool) -> [TestOptions -> IO TestResult]
forallAtoms x =
[ run (x :: Bool -> Bool)
, run (x :: Word8 -> Bool)
, run (x :: String -> Bool)
{- etc -} ]
containerTests = forallAtoms prop_AtomIdentity
But it fails with a typecheck error:
Tests/Containers.hs:33:0:
Couldn't match expected type `Word8' against inferred type `String'
In the first argument of `run', namely `(x :: Word8 -> Bool)'
In the expression: run (x :: Word8 -> Bool)
In the expression:
[run (x :: Bool -> Bool), run (x :: Word8 -> Bool),
run (x :: String -> Bool)]
Is there a better way to test a QC property against multiple types? If not, can forallAtoms be made to work or is that not supported by the type system?
I cannot compile your code, so ... blind shot:
try
forallAtoms :: (forall a. (Atomic a, Show a) => a -> Bool) -> [TestOptions -> IO TestResult]
as a type signature. This needs the -XRankNTypes language extension.
The problem you have, as I see it, is that GHC tries to find one type to insert for a in x :: (a -> Bool) for the entire function scope, but you already give three different there.