How to call a module dynamically in Erlang? - erlang

Assume I have two modules a.erl and b.erl. Both modules contains the same functions ( in Java I would say "both classes implement the same interface" ).
In module "c.erl" I want to have a function that will return module "a" or "b" ( depends on the parameter )
Here is what I want to have in module c.erl
-module(c)
get_handler(Id) ->
% if Id == "a" return a
% if Id == "b" return b
test() ->
get_handler("a"):some_function1("here were go for a"),
get_handler("a"):some_function2("aaaa"),
get_handler("b"):some_function1("here we go for b")
How can I make this work? I am relatively new to Erlang and don't know how to do it. In Java it would be very obvious, because you just return new instance of the class.

Just have get_handler/1 return the module name as an atom, and then use it to call the desired function:
(get_handler("a")):some_function2("aaaa"),
(get_handler("b")):some_function1("here we go for b").
Note that you need parentheses around the call to get_handler/1 in this case.
A simple version of get_handler/1 for modules a and b could be:
get_handler("a") -> a;
get_handler("b") -> b.

If you have an atom in a variable you can use it as a module name.
So, you could define c:get_handler/1 like this:
get_handler("a") -> a;
get_handler("b") -> b.
Your c:test/0 looks ok, except you need extra brackets, like this:
test() ->
(get_handler("a")):some_function1("here were go for a"),
(get_handler("a")):some_function2("aaaa"),
(get_handler("b")):some_function1("here we go for b").
Then in modules a and b just define a some_function1/1 and some_function/2, for example:
some_function1(Str) ->
io:format("module ~s function some_function1 string ~s~n", [?MODULE, Str]).
some_function2(Str) ->
io:format("module ~s function some_function2 string ~s~n", [?MODULE, Str]).
Edit: You should possibly also define a behaviour if you're going to do this sort of thing BTW, which would mean you would declare in modules a and b something like this:
-behaviour(some_behaviour).
Then create module some_behaviour something like this:
-module(some_behaviour).
-callback some_function1 (String :: string()) -> ok .
-callback some_function2 (String :: string()) -> ok .
This means any module like a and b that declare that they support the behaviour some_behaviour must define those functions, and the compiler will speak up if they don't. The types of the parameters and return value are also defined here for static analysis, etc.

Related

F# - (NUnit ApplyTo) member matches multiple overloads ... please restrict it to one

I'm trying to write custom equality constraint to compare 2 objects.
open FsUnit
open NUnit.Framework.Constraints
type equalCompany(expected:Company) =
inherit Constraints.EqualConstraint(expected)
override this.ApplyTo (actual:Company option) =
//actual.IsSome |> should equal True
//actual.Value.Id |> should equal expected.Id
ConstraintResult(this, actual, true)
// example of usage:
actualCompany |> should equalCompany expectedCompany
It complains because the ApplyTo implementation matches multiple overloads and I can't find the right syntax.
Ideally I like to compare to Company option but still just Company is fine.
The types involved are the following:
type CompanyType =
| Bank
| Exchange
type Company = {
Id: string
Types: CompanyType list
}
and I'm trying to write my equality constraint because the simple existing equal does not work properly with Types (the list, also if sorted, appears always different)
How can I properly override the ApplyTo function?
I think the issue is that the ApplyTo method that you are trying to override is generic and needs to have a signature ApplyTo<'T> : 'T -> ConstraintResult.
If I understand your code correctly, you are trying to define a comparison between Company and Company option. To Do this, you would need to check (at runtime) that the value passed to ApplyTo is of the right type. Then you can cast it and implement whatever logic you need.
Here is a minimal sample that worked for me, written as an F# script file:
#r "nuget: nunit"
#r "nuget: fsunit"
type Company(s) =
member x.Name = s
open FsUnit
open NUnit.Framework.Constraints
type equalCompany(expected:Company) =
inherit EqualConstraint(expected)
override this.ApplyTo<'T>(actual:'T) =
match box actual with
| :? option<Company> as co ->
ConstraintResult(this, actual,
co.IsSome && co.Value.Name = expected.Name)
| _ ->
ConstraintResult(this, actual, false)
let actualCompany = Company("Test")
let expectedCompany = Company("Test")
// This passes, because it has the right type
Some actualCompany |> should equalCompany expectedCompany
// This does not, because the 'ApplyTo' logic does not handle this type
actualCompany |> should equalCompany expectedCompany

How to specify the result type for F# function's signature?

I am still somewhat new to F#, I see myself struggling with some function signatures when the compiler fails to infer the type properly. In the Following example the compiler believed that the function type for TryParsewas string -> string so I had to create this definition with the lambda on the right side.
type SocialAccount =
| FacebookAccount
| UnknownAccount
type SocialAccount with
static member TryParse:(string -> SocialAccount option) = fun s ->
match s with
| "FACEBOOK" -> Some FacebookAccount
| _ -> None
I find that lambda after the equal a little bit ugly and decoupling the arg names from the types makes it a bit unreadable I think. Also create a type for every single complex function makes crowded namespaces.
Isn't there really anyway to define a function and specify its return type? I am looking for something like the following code (which is incorrect):
static member TryParse:(s:string -> SocialAccount option) =
match s with
| "FACEBOOK" -> Some FacebookAccount
| _ -> None
All suggestions are welcome. Including creative ones.
You can put a type annotation for the return value at the end of the declaration line:
static member TryParse(s: string): SocialAccount option =
As an aside, static member X = fun ... -> is not equivalent to static member X(...) =. The former creates a property, rather than a method.

How should i match the Elmish toNavigable argument types

I'm trying to learn the SAFE Stack at the moment, specifically attempting to handle URL navigation via Elmish; I've followed the example code on the Elmish site that defines a route mapping function and then passes that to the parsePath function.
However, Program.toNavigable expects a Parser<'a> type (a type alias for Location -> 'a) as its first argument, but the sample code (parsePath routes) first argument is a Location -> 'a option.
Obviously i can use function composition to get the correct typing, but it seems like I'm missing something here. Can anyone familiar with URL navigation in Elmish advise?
Well, a Parser<'a option> is a Parser<'a> (just with another 'a), so things should compose just fine.
Say, e.g., that the following type defines all navigation:
type Route = Blog of int | Search of string
Then the parties involved should have the following types:
init: Route option -> Model * Cmd<Msg>
parser: Parser<Route option>
urlUpdate: Route option -> Model -> Model * Cmd<Msg>
and you compose your program thusly:
Program.mkProgram init update view
|> Program.toNavigable parser urlUpdate
|> Program.withReactBatched "elmish-app"
|> Program.run

'No type class instance was found' on multi-parameter type class

Is it reasonable to have multi parameter type classes in PureScript?
The compiler raises an unreasonable 'No type class instance was found' error (see full output) for the below type class definition:
class Transform model turn where
transform :: turn -> model -> model
delay :: Maybe turn -> Int
The error arises from the definition of the delay function which doesn't depend on the model type parameter. As evident from the compiler output linked above it substitutes a t0 for the absent model.
What is the proper way to fix this? Currently I workaround this issue by changing the kind of turn as below:
class Turnable model turn where
runTurn :: turn model -> model -> model
turnDelay :: Maybe (turn model) -> Int
rightfold from the FP slack channel gave this answer:
add fundep | turn -> model
Then the instance is looked up only through turn
Consequently I changed the type class definition to this:
class Turnable model turn | turn -> model where
runTurn :: turn -> model -> model
turnDelay :: Maybe turn -> Int
This made the compiler happy. For details, consult Functional dependencies (fundep) in the Haskell wiki and the 24 days of PureScript post.
...in the old days we had used a Proxy (https://github.com/purescript/purescript-proxy) to help the compiler decide which instance to choose.
e.g. :
turnDelay :: Proxy model -> turn -> Int
turnDelay _ turn = .....
and call it by passing in a proxy:
turnDelay (Proxy :: Proxy FooModel) barTurn
I agree FunDeps are the right way to go.

F# using with indent syntax

there is
using (new SqlConnection(insql)) ( Open(); )
or
using (new SqlConnection(insql)) <| fun c ->
c.Open()
I want indent but without c alike
using (new SqlConnection(insql)) ->
Open()
How can I do it ?
There's no way to do that; since Open is an instance method it needs to be preceded by the object which it's being called on.
I'd typically avoid using entirely and use a use-binding:
use c = new SqlConnection(insql)
c.Open()

Resources