I'm trying to write a function that calls a function with a specified name and arity:
my_fun(FunctionName, Arity) ->
%Call FunctionName/Arity
.
So that calling it like this:
my_fun(foo, 3)
should result in a call to function foo/3.
The problem is, I don't know how to call a function if only its name and arity are specified. The function I'm trying to call is guaranteed to exist in the same module from which I'm trying to call it.
Is it possible to implement this in Erlang, and how?
You can use erlang:apply/3 with the first argument being ?MODULE to refer to the same module, the second one being the name of the function as an atom and the third one being a list containing Arity elements:
-module(a).
-compile(export_all).
my_fun(FunctionName, Arity) ->
apply(?MODULE, FunctionName, lists:seq(1, Arity)).
foo(A, B, C) ->
io:format("~p ~p ~p~n", [A, B, C]).
bar(A, B) ->
io:format("~p ~p~n", [A, B]).
main() ->
my_fun(foo, 3),
my_fun(bar, 2).
Output:
1> c(a), a:main().
1 2 3
1 2
Not really clear what you want to do...
Does this help you?
-module (cf).
-export ([cf/2,test/0,f/1,f/2,f/3]).
cf(F,1) ->
fun(P1) -> apply(cf,F,[P1]) end;
cf(F,2) ->
fun(P1,P2) -> apply(cf,F,[P1,P2]) end;
cf(F,3) ->
fun(P1,P2,P3) -> apply(cf,F,[P1,P2,P3]) end.
f(X) -> lists:seq(1,X).
f(X,Y) -> X+Y.
f(X,Y,Z) -> {X,Y,Z}.
test() ->
A = cf(f,1),
B = cf(f,2),
C = cf(f,3),
{A(3),B(5,6),C(a,12,"hello")}.
1> c(cf).
{ok,cf}
2> cf:test().
{[1,2,3],11,{a,12,"hello"}}
But this is just hiding the function: apply(Module,Function,Args), I don't see the advantage to do not use it directly.
Related
The minimal code:
twice :: (a -> a) -> a -> a
twice f = f . f
main = do
return twice ++ "H"
The errors generated:
stack runhaskell "c:\Users\FruitfulApproach\Desktop\Haskell\test.hs"
C:\Users\FruitfulApproach\Desktop\Haskell\test.hs:5:1: error:
* Couldn't match expected type `IO t0'
with actual type `[(a0 -> a0) -> a0 -> a0]'
* In the expression: main
When checking the type of the IO action `main'
|
5 | main = do
| ^
C:\Users\FruitfulApproach\Desktop\Haskell\test.hs:6:20: error:
* Couldn't match type `Char' with `(a -> a) -> a -> a'
Expected type: [(a -> a) -> a -> a]
Actual type: [Char]
* In the second argument of `(++)', namely `"H"'
In a stmt of a 'do' block: return twice ++ "H"
In the expression: do return twice ++ "H"
* Relevant bindings include
main :: [(a -> a) -> a -> a]
(bound at C:\Users\FruitfulApproach\Desktop\Haskell\test.hs:5:1)
|
6 | return twice ++ "H"
| ^^^
How would I logically fix this issue myself? Clearly it's something I'm doing wrong. Am I missing a preamble that every example should have?
As RobinZigmond mentions in the comments, you can’t write twice ++ "H". This means, ‘take the function twice, and append the string "H" to it’. This is clearly impossible, since ++ can only append strings and lists together. I suspect that what you meant was twice (++ "H"). This takes the function (++ "H"), which appends "H" to the end of its argument, and runs it twice.
But even if you do this, there is still a problem. Take a look at the program which is created if you do this:
twice :: (a -> a) -> a -> a
twice f = f . f
main = do
return (twice (++ "H"))
Even though this program compiles, it doesn’t do anything! You have set twice (++ "H")) as the return value of main, but the return value of main is always ignored. In order to produce output, you need to use putStrLn instead of return:
twice :: (a -> a) -> a -> a
twice f = f . f
main = do
putStrLn (twice (++ "H"))
But this program doesn’t work either! twice (++ "H") is a function, which cannot be printed. This function must be applied to a value in order to produce a result:
twice :: (a -> a) -> a -> a
twice f = f . f
main = do
putStrLn (twice (++ "H") "Starting value")
This program should finally work, giving an output of Starting valueHH when it is run.
Can somebody point me to how to feed data to:
twice f x = f (f x)
It's taken from Erik Meijer's lecture, and I have the feeling I can only truely understand when passing data to it. Now this only results in errors.
The derived type signature is (t -> t) -> t -> t. Pass any arguments that match and you won't get compiler errors. One example is twice (+1) 0.
The main mistake here is disregarding the type of twice. In Haskell types are very important, and explain precisely how you would call such a function.
twice :: (a -> a) -> a -> a
So, the function works in this way:
the caller chooses any type a they want
the caller passes a function f of type a -> a
the caller passes an argument of type a
twice finally produces a value of type a
Hence, we could do the following. We can choose, for instance, a = Int. Then define the function f as
myFun :: Int -> Int
myFun y = y*y + 42
then choose x :: Int as 10. Finally, we can make the call
twice myFun 10
Alternatively, we can use a lambda and skip the function definition above
twice (\y -> y*y + 42) 10
For illustration here are three functions called erik1, erik2, and erik3 with the same type signature.
erik1, erik2, erik3 ::(a -> a) -> a -> a
erik1 f x = f x
erik2 f x = f(f x) -- Equivalent to "twice"
erik3 f x = f(f(f x))
These eriks take two arguments, the first being a function and the second being a number. Let's choose sqrt as the function and the number to be 16 and run the three eriks. Here's what you get:
*Main> erik1 sqrt 16
4.0
*Main> erik2 sqrt 16
2.0
*Main> erik3 sqrt 16
1.4142135623730951
There are many things you can try, such as erik3 (/2) 16 = 2,because the f in the function allows you to use any appropriate function. In the particular case of sqrt, erik3 is equivalent to this statement in C:
printf ("Eighth root of 16 = %f \n", sqrt(sqrt(sqrt(16))));
Dr. Meijer Ch 7 1:48 to 3:37
As I watched this lecture last night a key point was made when Erik wrote the type signature as twice :: (a -> a) -> (a -> a) and said, "twice is a function that takes a to a and returns a new function from a to a, and by putting some extra parens it becomes painfully obvious that twice is a higher order function."
A C example that comes closer to illustrating that is:
#define eighthRoot(x) (sqrt(sqrt(sqrt(x))))
printf ("eigthtRoot(16) = %f \n", eighthRoot(16));
This question already has answers here:
Haskell recursive function example with foldr
(2 answers)
Closed 6 years ago.
module Tf0 where
all' :: (a -> Bool) -> [a] -> Bool
all' p = foldr (&&) True . map p
main :: IO()
xs = [1,3,5,7,9]
xs1 = [1,3,11,4,15]
k1 = all' (<10) xs
k2 = all' (<10) xs1
k3 = all' (<10)
main = print k1
Questions:
In the function definition (all' p = foldr (&&) True . map p) there is no list as an input while the function Type shows a list as an input ([a]), yet trying to check the function (see bellow k1, k2, k3) shows that a list is needed.
How can the function be defined without the list?
One of the fundamental aspects of Haskell is that conceptually a function always takes one argument. Indeed take for instance the function (+):
(+) :: Int -> Int -> Int
(technically it is (+) :: Num a => a -> a -> a, but let us keep things simple).
Now you can argue that (+) takes two arguments, but conceptually it takes one argument. Indeed: the signature is in fact
(+) :: Int -> (Int -> Int)
So you feed it one integer and now it returns a function, for instance:
(+) 5 :: Int -> Int
So you have, by giving it a 5, constructed a function that will add 5 to a given operand (again a function that takes one argument).
Now applying this to your question, the signature of all' is in fact:
all' :: (a -> Bool) -> ([a] -> Bool)
So if you apply all' with one argument, it returns a function that maps a list [a] to a Bool. Say for the sake of argument that we set p to \_ -> True, then we return:
foldr (&&) True . map (\_ -> True) :: [a] -> Bool
so indeed a function that takes a list [a] and maps it on a Bool. In a next phase you apply a list to that (returning) function.
In other words, functional programming can be seen as a long chain of specializing a function further and further until it is fully grounded and can be evaluated.
Haskell only provides this in an elegant way such that you do not have to think about functions generating functions. But conceptually, this happens all the time. Given you want to implement a function f :: a -> b -> c, you can do this like:
f x y = g (x+1) y
(with g :: a -> b -> c), but you can also decide to leave a parameter out, and define it as:
f x = g (x+1)
since g (x+1) will return a function that can apply with the y eventually.
I try to print functions in Haskell only for fun, like this example:
{-# LANGUAGE FlexibleInstances #-}
instance Show (Int -> Bool) where
show _ = "function: Int -> Bool"
loading in GHCi and run and example:
λ> :l foo
[1 of 1] Compiling Main ( foo.hs, interpreted )
foo.hs:2:1: Warning: Unrecognised pragma
Ok, modules loaded: Main.
λ> (==2) :: Int -> Bool
function: Int -> Bool
But, I wish to see that every function print yourself at invocation.
You can not have this for a general function as type information is present only at compile time, but you use Typeable class for writing something close enough if the type is an instance for Typeable class.
import Data.Typeable
instance (Typeable a, Typeable b) => Show (a -> b) where
show f = "Function: " ++ (show $ typeOf f)
Testing this in ghci
*Main> (+)
Function: Integer -> Integer -> Integer
*Main> (+10)
Function: Integer -> Integer
But this will not work for general functions until the type is restricted to a type that has Typeable instance.
*Main> zip
<interactive>:3:1:
Ambiguous type variable `a0' in the constraint:
(Typeable a0) arising from a use of `print'
Probable fix: add a type signature that fixes these type variable(s)
In a stmt of an interactive GHCi command: print it
<interactive>:3:1:
Ambiguous type variable `b0' in the constraint:
(Typeable b0) arising from a use of `print'
Probable fix: add a type signature that fixes these type variable(s)
In a stmt of an interactive GHCi command: print it
*Main> zip :: [Int] -> [Bool] -> [(Int,Bool)]
Function: [Int] -> [Bool] -> [(Int,Bool)]
I'm assuming that you want the show method to print the function's address, which is what Python does:
>>> def foo(a):
... return a
...
>>> print foo
<function foo at 0xb76f679c>
There is really no supported way to do it (Haskell is a safe, high-level language that abstracts from such low-level details as function pointers), unless you're willing to use the internal GHC function unpackClosure#:
{-# LANGUAGE MagicHash,UnboxedTuples,FlexibleInstances #-}
module Main
where
import GHC.Base
import Text.Printf
instance Show (a -> a) where
show f = case unpackClosure# f of
(# a, _, _ #) -> let addr = (I# (addr2Int# a))
in printf "<function ??? at %x>" addr
main :: IO ()
main = print (\a -> a)
Testing:
$ ./Main
<function ??? at 804cf90>
Unfortunately, there is no way to get the function's name, since it is simply not present in the compiled executable (there may be debug information, but you can't count on its presence). If your function is callable from C, you can also get its address by using a C helper.
I have an assignment and am currently caught in one section of what I'm trying to do. Without going in to specific detail here is the basic layout:
I'm given a data element, f, that holds four different types inside (each with their own purpose):
data F = F Float Int, Int
a function:
func :: F -> F-> Q
Which takes two data elements and (by simple calculations) returns a type that is now an updated version of one of the types in the first f.
I now have an entire list of these elements and need to run the given function using one data element and return the type's value (not the data element). My first analysis was to use a foldl function:
myfunc :: F -> [F] -> Q
myfunc y [] = func y y -- func deals with the same data element calls
myfunc y (x:xs) = foldl func y (x:xs)
however I keep getting the same error:
"Couldn't match expected type 'F' against inferred type 'Q'.
In the first argument of 'foldl', namely 'myfunc'
In the expression: foldl func y (x:xs)
I apologise for such an abstract analysis on my problem but could anyone give me an idea as to what I should do? Should I even use a fold function or is there recursion I'm not thinking about?
The type of foldl is
foldl :: (a -> b -> a) -> a -> [b] -> a
but the type of func is
-- # a -> b -> a
func :: F -> F -> Q
The type variable a cannot be simultaneously F and Q, thus the error.
If the Q can be converted to and from F, you could use
myfunc y xs = foldl (func . fromQ) (toQ y) xs
where
func . fromQ :: Q -> F -> Q
toQ y :: Q
xs :: [F]
so this satisfies all the type requirements, and will return the final Q.
maybe you need map?
map :: (f -> q) -> [f] -> [q]
it evaluates a function on each element in a list and gives a list of the results. I'm not sure why your function takes two Fs though, possibly to work with foldl?