The function below compiles and runs fine.
I do not intend to create them like this (without parameter names).
However because it lets me create such a function, I am curious how I can access them within the function.
let testfunction string int =
printfn "Inside Method"
testfunction "a" 5
Here is the F# interactive output
Inside Method
val testfunction: string: 'a -> int: 'b -> unit
val it: unit = ()
Thank you for your help in advance.
Actually, string and int are the parameter names, so you access them like any other parameters:
let testfunction string int =
printfn $"string is {string}"
printfn $"int is {int}"
testfunction "a" 5
Output is:
string is a
int is 5
To reduce confusion, you could declare the function like this:
let testfunction (string : string) (int : int) =
printfn $"string is {string}"
printfn $"int is {int}"
Related
I am new to F# and am trying to chain functions to make a Higher Order Function.
A simplified example is
init returns a tuple
validate accepts a tuple and returns bool
let init : string * string =
("1", "2")
let validate ((a: string), (b: string)) : bool =
a.Equals(b)
let test = init >> validate
ERROR
This expression was expected to have type 'a -> 'b' but here has type 'string * string'
As the answer for Piotr explains, you are getting an error because you have a value and a function. To compose those, you can turn init into a function, but you do not really need to use composition in this case.
If you want to pass a value as an argument to a function, it is typically much simpler to just pass it as an argument:
let res = validate init
Alternatively, if you have a number of functions you want to apply to your input in a sequence, you can do this using the piping operator:
let res = init |> validate
Function composition using >> is a nice functional trick, but I think it is actually much less common in standard F# code than most people think. I use |> all the time, but >> only rarely.
You can only compose functions using the >> combinator. Your first assignment is not a function - it is a binding to a value - your tuple.
You can convert it to a function just by adding empty parameter list () (unit) parameter like this:
let init() : string * string =
("1", "2")
let validate ((a: string), (b: string)) : bool =
a.Equals(b)
let test = init >> validate
let res = test()
I'm pretty sure this isn't possible but thought I'd double check. I guess I'm trying to mimic typescript's union types.
I have a type
type StringOrInt =
| String of string
| Int of int
And then a function
let returnSelf (x: StringOrInt) = x
At the moment the function has to be called like
returnSelf (String "hello")
Is it possible to do
returnSelf "hello"
and infer that it is a valid StringOrInt?
At the moment it's not supported out of the box, but fairly simple generic casting method can be implemented.
Given an example function:
let call v = (* v has inferred type StringOrInt *)
match v with
| String s -> printfn "called a string %s" s
| Int i -> printfn "called an int %i" i
We could eventually call it like so:
(* % is a unary prefix operator *)
call %"abc"
call %1
We need to provide some way to tell how to convert ordinary string/int into StringOrInt type. This can be used by exemplar convention call:
type StringOrInt =
| String of string
| Int of int
static member inline From(i: int) = Int i
static member inline From(s: string) = String s
Here our discriminated union provides two static methods which are responsible for casting. Since they correspond to the same naming convention, we can use them together with F# statically resolved generic type parameters - these are generics that are resolved at compile time unlike the .NET generics which exists also at runtime - to create a casting function (or operator):
(* casting operator *)
let inline (~%) (x: ^A) : ^B =
(^B : (static member From: ^A -> ^B) x)
This way you can use % prefix operator over any type that implements a casting mechanism in form of static From method.
I have read about continuations and partial applications; I am also aware of the kprintf function.
But I still don't know how to write something like:
let myPrintFunction format variable_length_arguments_list =
let a = sprintf format variable_length_ argument_list
do other things
what would be the syntax this this?
so I could use it like:
myPrintFunction "%s : %i" "hello" 3
Edit:
This is different than How do I implement a method with a variable number of arguments? because that question is asking how to make a method with a variable number of arguments, but the issue I am facing is to pass that variable number of argument to the next function (sprintf) that takes a variable number of arguments too.
Or, at least that's where I suppose the problem is.
The test code, based on the solution proposed by Scott can be found here: https://dotnetfiddle.net/oCzcS9
I want to demonstrate the ksprintf function, because that one accepts a continuation that will allow you to pass on the resulting string to e.g. a log system.
For the purpose of demonstration, let's first create something that can take a single string as input and pass it on, in this case to the console.
let writeStringToConsole (s: string) = Console.WriteLine ("OUTPUT : " + s)
So now, if writeStringToConsole is all we have, how to we make it accept F# formatting?
let printToConsole format = Printf.ksprintf writeStringToConsole format
Example that demonstrates that it works.
type DU = A | B
let i = 7
let s = "thirteen"
let du = B
printToConsole """an int %i and a string "%s" here""" i s
printToConsole """an int %i and a string "%s" and DU %A here""" i s du
// OUTPUT : an int 7 and a string "thirteen" here
// OUTPUT : an int 7 and a string "thirteen" and DU B here
// Note that OUTPUT is also part of the actual output,
// and it demonstrates how you can add e.g. a timestamp
// or line number or something to the output string, without
// it being part of the formatting.
edit: Some additional notes
The format string must be a literal. That's because the literal string must be read at compile time in order to compute the function that must be returned in order to gobble up whatever values/types that follow the format string.
For example, if you do printToConsole "%i %s %A %A" 7 "x" myType yourType, then you'll see int -> string -> MyType -> YourType in the signature of printToConsole where it's used.
There is a way to use plain strings as format strings with this system, but I don't remember how it's done, and anyway it spoils the type safety. It comes in handy when doing internationalization of strings, and your format strings must come from a resource and not F# source due to external translator services.
edit 2 : Wrap e.g. log system
I created an interface to use for various logging systems, which pretty much share the same features.
type ILogger =
...
abstract member Debugf: StringFormat<'h, unit> -> 'h
abstract member Verbosef: StringFormat<'h, unit> -> 'h
abstract member Infof: StringFormat<'h, unit> -> 'h
abstract member Warningf: StringFormat<'h, unit> -> 'h
abstract member Errorf: StringFormat<'h, unit> -> 'h
abstract member Fatalf: StringFormat<'h, unit> -> 'h
Then an implementation for my currently used logging system looks like this.
type internal SiLogger(session: Session) =
let slogf = Printf.ksprintf
...
interface ILogger with
...
member _.Debugf format = slogf session.LogDebug format
member _.Verbosef format = slogf session.LogVerbose format
member _.Infof format = slogf session.LogMessage format
member _.Warningf format = slogf session.LogWarning format
member _.Errorf format = slogf session.LogError format
member _.Fatalf format = slogf session.LogFatal format
And there is a null logger.
let slogf = Printf.ksprintf
let dummyLog _ = () // The parameter is the title string.
let dummy format = slogf dummyLog format
let getNullLogger () =
{ new ILogger with
...
member _.Debugf format = dummy format
member _.Verbosef format = dummy format
member _.Infof format = dummy format
member _.Warningf format = dummy format
member _.Errorf format = dummy format
member _.Fatalf format = dummy format
...
}
open System
let myPrintFunction (format: Printf.StringFormat<_>) ([<ParamArray>] args) =
let a = sprintf format args
a
myPrintFunction "%s : %i" "hello" 3
To add the PrintF as a member function, this is the closest I could get. As you see, I had to pass the format string separately (in the constructor, or I could have used a property setter). I could find no way to pass the format string as the first parameter of the PrintF function as I could for a free function (see my other answer at https://stackoverflow.com/a/58822618/5652483).
Also, if I uncomment the line this.RaiseSomeEvent msg, then it breaks. So I could find no way to enable the PrintF function to have a side effect.
Hopefully, someone else can solve these issues.
type Foo (format: Printf.StringFormat<_>) =
member this.RaiseSomeEvent msg = printf "%s" msg
member this.PrintF ([<ParamArray>] args) =
let msg = sprintf format args
//this.RaiseSomeEvent msg
msg
let foo = Foo("%s : %i")
foo.PrintF "hello" 3
Here is a simple composition of functions in F#
let composedFunction = System.Text.Encoding.UTF8.GetBytes >> Array.length
"test" |> composedFunction
Type inference correctly defines the type of composed function string -> int. But compiler cannot pick correct overload of System.Text.Encoding.UTF8.GetBytes method:
Error FS0041: A unique overload for method 'GetBytes' could not be
determined based on type information prior to this program point. A
type annotation may be needed. Candidates:
System.Text.Encoding.GetBytes(chars: char []) : byte [],
System.Text.Encoding.GetBytes(s: string) : byte []Blockquote
Is there any way to compose correct overload of System.Text.Encoding.UTF8.GetBytes which accepts string parameter?
Or course, I can do following
// declare function which calls correct overload and then use it for compostion
let getBytes (s: string) = System.Text.Encoding.UTF8.GetBytes s
let composedFunction = getBytes >> Array.length
// start composition with ugly lambda
let composedFunction =
(fun (s: string) -> s) >> System.Text.Encoding.UTF8.GetBytes >> Array.length
But I wonder if there is any way without additional function declarations to make the compiler pick right overload according to the inferred string -> int type of composed function?
You can always add annotations:
let composedFunction : string -> _ = System.Text.Encoding.UTF8.GetBytes >> Array.length
or
let composedFunction = (System.Text.Encoding.UTF8.GetBytes : string -> _) >> Array.length
As your example shows, .NET methods do not always compose well - I think the idiomatic approach in such situations is just to use the .NET style when you're dealing with .NET libraries (and use functional style when you're dealing with functional libraries).
In your specific case, I would just define a normal function with type annotation and get the length using the Length member rather than using the function:
let composedFunction (s:string) =
System.Text.Encoding.UTF8.GetBytes(s).Length
The existing answer shows how to get the composition to work with type annotations. Another trick you can do (which I would definitely not use in practice) is that you can add identity function on string to the composition to constrain the types:
let composedFunction = id<string> >> System.Text.Encoding.UTF8.GetBytes >> Array.length
It's fun that this works, but as I said, I would never actually use this, because a normal function as defined above is much easier to understand.
This question already has answers here:
Call F# code from C#
(4 answers)
Closed 8 years ago.
I am SQL developer and am really new to both F# and C#. I need help on how to pass a string to f# function below and to return the result from F# to C#.
Description of project:
I am using stanford postagger to tag a sentence with the parts of speech.
Reference link from where i copied this code.
(http://sergey-tihon.github.io/Stanford.NLP.NET/StanfordPOSTagger.html)
module File1
open java.io
open java.util
open edu.stanford.nlp.ling
open edu.stanford.nlp.tagger.maxent
// Path to the folder with models
let modelsDirectry =
__SOURCE_DIRECTORY__ + #'..\stanford-postagger-2013-06-20\models\'
// Loading POS Tagger
let tagger = MaxentTagger(modelsDirectry + 'wsj-0-18-bidirectional-nodistsim.tagger')
let tagTexrFromReader (reader:Reader) =
let sentances = MaxentTagger.tokenizeText(reader).toArray()
sentances |> Seq.iter (fun sentence ->
let taggedSentence = tagger.tagSentence(sentence :?> ArrayList)
printfn "%O" (Sentence.listToString(taggedSentence, false))
)
// Text for tagging
let text = System.Console.ReadLine();
tagTexrFromReader <| new StringReader(text)
it won't matter if C# or F# - do make a function that gets a string and returns ... let
s say an int, you just need something like this (put it in some MyModule.fs):
namespace MyNamespace
module MyModule =
// this is your function with one argument (a string named input) and result of int
let myFun (input : string) : int =
// do whatever you have to
5 // the value of the last line will be your result - in this case a integer 5
call it in from C#/.net with
int result = MyNamespace.MyModule.myFun ("Hallo");
I hope this helps you out a bit
For your example this would be:
let myFun (text : string) =
use reader = new StringReader(text)
tagTexrFromReader reader
as you'll have this in the module File1 you can just call it with var res = Fiel1.myFun(text);
BTW: use is in there because StringReader is IDisposable and using use F# will dispose the object when you exit the scope.
PS: is tagTexrFromReader a typo?