Conclusion type understanding the problem when returning a function from a function in FSharp

I use log4net in my F # application and wanted to make the recording more logical with F # by creating several functions.

For warnings, I created the following function:

let log = log4net.LogManager.GetLogger("foo")
let warn format = Printf.ksprintf log.Warn format

This works very well, and I can do:

warn "This is a warning"
// and
warn "The value of my string is %s" someString

However, I wanted to make it more universal and make it possible to go through the logger that I wanted. Thus, I wrapped the function in another function that can accept ILog as a parameter:

let getWarn (logger: log4net.ILog) =
    fun format -> Printf.ksprintf logger.Warn format

and I also tried:

let getWarn (logger: log4net.ILog) format =
    Printf.ksprintf logger.Warn format

When I now use it like this:

let warn = getWarn log4net.LogManager.GetLogger("bar")
warn "This is a warning"

This works, however, when I do this:

warn "The value of my string is %s" someString

I get a compiler error saying "The value is not a function and cannot be applied" If I delete the first warning statement, it will work.

, , , , warn, , .

, warn , getWarn?

+4
1

.

warn , , . , ( , - , ), , , .

warn ( ). : Value restriction. The value 'warn' has been inferred to have generic type. , .

, , F # : , . , . .

, warn " ", " ". :

let warn() = getWarn log4net.LogManager.GetLogger("bar")

( - . ) generic, :

let warn<'a> : StringFormat<'a, unit> -> 'a = log4net.LogManager.GetLogger("bar")

, , .

, , :

warn "This is a warning"
warn "The value of my string is %s" someString

: , ( , ). unit. ( ) , , warn, , .. , warn, getWarn GetLogger . , , , , .

: , . . , , . :

let mapTuple f (a,b) = (f a, f b)
let makeList x = [x]

mapTuple makeList (1, "abc")

, - ( [1], ["abc"] ), ? , . mapTuple f (a,b), f . , a b, . -: f , , a, b, a b , mapTuple: ('a -> 'b) -> 'a*'a -> 'b*'b.

, , warn, , . , ( ), : , , .

, ( ), , . - :

type loggers =
    abstract member warn: Printf.StringFormat<'a, unit> -> 'a
    abstract member err: Printf.StringFormat<'a, unit> -> 'a

let getLoggers (log: log4net.ILog) = 
  { new loggers with
    member this.warn format = Printf.ksprintf log.Warn format
    member this.err format = Printf.ksprintf log.Error format }

let logs = getLoggers (log4net.LogManager.GetLogger("Log"))

logs.warn "This is a warning"
logs.warn "Something is wrong: %s" someString
+8

Source: https://habr.com/ru/post/1657027/


All Articles