Is there a way to make this continuation a continuation with an example codata example in F #?

type Interpreter<'a> =
| RegularInterpreter of (int -> 'a)
| StringInterpreter of (string -> 'a)

let add<'a> (x: 'a) (y: 'a) (in_: Interpreter<'a>): 'a = 
    match in_ with
    | RegularInterpreter r -> 
        x+y |> r
    | StringInterpreter r -> 
        sprintf "(%s + %s)" x y |> r

The error message that he cannot solve 'aat compile time is completely clear to me. I guess the answer to the question of whether the above work can be done is not just adding functions directly to the data type. But then I could use the interface or completely get rid of the general parameters.

Edit: Mark the answer, really do what I asked, but let me ask the question, as I did not explain it properly. What I'm trying to do is to do with the above technique, mimics what was done in this post . The motivation for this is to avoid built-in functions, since they have poor compositional ability - they cannot be transmitted as lambda without specialized arguments.

I was hoping I could get around it by passing a union type with a common argument to close, but ...

type Interpreter<'a> =
| RegularInterpreter of (int -> 'a)
| StringInterpreter of (string -> 'a)

let val_ x in_ =
    match in_ with
    | RegularInterpreter r -> r x
    | StringInterpreter r -> r (string x)

let inline add x y in_ = 
    match in_ with
    | RegularInterpreter r -> 
        x in_ + y in_ |> r
    | StringInterpreter r -> 
        sprintf "(%A + %A)" (x in_) (y in_) |> r

let inline mult x y in_ = 
    match in_ with
    | RegularInterpreter r -> 
        x in_ * y in_ |> r
    | StringInterpreter r -> 
        sprintf "(%A * %A)" (x in_) (y in_) |> r

let inline r2 in_ = add (val_ 1) (val_ 3) in_

r2 (RegularInterpreter id)
r2 (StringInterpreter id) // Type error.

This last line gives a type error. Is there any way around this? Although I would prefer that the functions were not built-in due to the limitations that they impose on the composition.

+4
4

:

let inline add x y in_ = 
    match in_ with
    | RegularInterpreter r -> 
        x + y |> r
    | StringInterpreter r -> 
        sprintf "(%A + %A)" x y |> r

, :

  • , sprintf, . %s, , , x y string .
  • inline.

add :

x: ^a -> y: ^b -> in_:Interpreter<'c> -> 'c
    when ( ^a or  ^b) : (static member ( + ) :  ^a *  ^b -> int)

, , + int. , , int, .

FSI:

> add 3 2 (RegularInterpreter id);;
val it : int = 5
> add 2 3 (StringInterpreter (fun _ -> 42));;
val it : int = 42
+4

int, , , F #. .

, , FSharp.Interop.Dynamic, , .

+3

, , , . , , :

let vale (x,_,_) = x
let adde (_,x,_) = x
let multe (_,_,x) = x

let val_ x d =
    let f = vale d
    f x

let add x y d =
    let f = adde d
    f (x d) (y d)

let mult x y d =
    let f = multe d
    f (x d) (y d)

let in_1 =
    let val_ (x: int) = x
    let add x y = x+y
    let mult x y = x*y
    val_,add,mult

let in_2 =
    let val_ (x: int) = string x
    let add x y = sprintf "(%s + %s)" x y
    let mult x y = sprintf "(%s * %s)" x y
    val_,add,mult

let r2 d = add (val_ 1) (val_ 3) d

//let test x = x in_1, x in_2 // Type error.

let a2 = r2 in_1 // Works
let b2 = r2 in_2 // Works

, , , , , . , , , .

, HKT , - . , "- ", Reddit, Haskell , - , , .

, , F #. , , , .

+2

Unfortunately, it’s not entirely clear to me what you are trying to do. However, it seems likely that this is possible by creating an interface using a common method. For example, here is how you can get your response code for work:

type I = abstract Apply : ((int -> 'a) * ('a -> 'a -> 'a) * ('a -> 'a -> 'a)) -> 'a

//let test x = x in_1, x in_2 // Type error.
let test (i:I) = i.Apply in_1, i.Apply in_2

let r2' = { new I with member __.Apply d = add (val_ 1) (val_ 3) d }
test r2' // no problem

If you want to use a value (for example, input a function) in the general case, then in most cases the cleanest way is to create an interface using the general method, whose signature expresses the desired polymorphism.

+2
source

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


All Articles