F# Monad how fix datatypes - f#

I am trying to write a Monad in F# but I can not compile the code and I am getting error FS0001
error: This expression was expected to have type 'Result' but here has type '(Result<'a> -> Result<'b>) -> Result<'b>'
open System
type Result<'TSuccess> =
| Success of 'TSuccess
| Failure
let bind x f =
match x with
| Success x -> f (Success x)
| Failure -> Failure
let stringToInt (s:string) =
try
let result = s |> int
Success result
with
|_-> Failure
let isPositive (i:int) =
if ( i > 0) then Success i : Result<int>
else Failure
let toString (i:int) =
try
let result = i |> string
Success result
with
|_ -> Failure
let bindIsPositive = bind isPositive : Result<int>
let bindToString = bind toString : Result<string>
let (>>=) x f = bind f x
let strintToIntIsPositiveIntToString s = stringToInt >>= bindIsPositive >>= bindToString
[<EntryPoint>]
let main argv =
printfn "10"
let mys = strintToIntIsPositiveIntToString "9"
Console.WriteLine mys.ToString
0 // return an integer exit code

First of all, the type of your bind is not right:
your version : Result<'a> -> (Result<'a> -> Result<'b>) -> Result<'b>
typical type : Result<'a> -> ('a -> Result<'b>) -> Result<'b>
It will also be a lot easier to do the rest if you switch the order of parameters to get:
bind : ('a -> Result<'b>) -> Result<'a> -> Result<'b>
So, you can use the following bind:
let bind f x =
match x with
| Success x -> f x
| Failure -> Failure
Once you do this, you can define bindIsPositive and bindToString. The bind operation now takes a function as a first argument, so this works but you have to remove your type annotation:
let bindIsPositive = bind isPositive
let bindToString = bind toString
When composing functions, you can then either use your >>= operator, or use normal F# piping and bind functions:
let strintToIntIsPositiveIntToString x = x |> stringToInt |> bindIsPositive |> bindToString
let strintToIntIsPositiveIntToString x = x >>= stringToInt >>= isPositive >>= toString

Related

How to print function argument name that was used to call this function in F#

How can I print argument function name that was used to call this function?
open System
open System.Threading.Tasks
let logger (f: ('a -> Task<'b>)) : ('a -> Task<'b>) =
printfn "Hey: %O" (nameof f) // I would like to print "myFunc", not "f"
f
let myFunc x = task {return x }
let d = (logger myFunc) 3
You could use the ReflectedDefinition(true) attribute, which automatically quotes the argument of a method call and gives you both the value (to use at runtime) and the code quotation from which you can (if the format is right) extract the name. This only seems to work with method calls though:
type Logger =
static member log([<ReflectedDefinition(true)>]f: Expr<('a -> Task<'b>)>) : ('a -> Task<'b>) =
match f with
| Patterns.WithValue(v, _, Patterns.Lambda(_, Patterns.Call(_, mi, _))) ->
printfn "Hello %s!" mi.Name
unbox v
| _ -> failwith "Wrong format"
let myFunc x = task {return x }
let d = (Logger.log myFunc) 3
The design and motivation of this is discussed in the F# 4.0 Speclet: Auto-Quotation of Arguments at Method Calls

InvalidOperationException on conversion from F# quotation to Linq Expression

I'm trying to substitute types in a F# Expr, before converting it to an Expression for consumption by a c# lib.
But upon the call to LeafExpressionConverter.QuotationToExpression I receive the error
InvalidOperationException: The variable 't' was not found in the translation context
Basically I'm trying to substitute the equivalent of
<# fun (t: Record) -> t.A = 10 #> to
<# fun (t: Dict) -> t["A"] = 10 #>
Here is the code
type Record = {
A: int
}
type Dict () = //this is the type the c# lib wants (a dictionary representation of a type)
inherit Dictionary<string, obj>()
let substitute<'a> (ex: Expr<'a->bool>) =
let replaceVar (v: Var) = if v.Type = typeof<'a> then Var(v.Name, typeof<Dict>) else v
let tEntityItem = typeof<Dict>.GetProperty("Item")
let isATypeShapeVar = function | ShapeVar var -> var.Type = typeof<'a> | _ -> false
let rec substituteExpr =
function
| PropertyGet(exOpt, propOrValInfo, c) ->
match exOpt with
| None -> Expr.PropertyGet(propOrValInfo)
| Some ex ->
let args = c |> List.map substituteExpr
let newex = substituteExpr ex
match isATypeShapeVar ex with
| true ->
let getter = Expr.PropertyGet(newex, tEntityItem, [Expr.Value(propOrValInfo.Name)] )
Expr.Coerce(getter, propOrValInfo.PropertyType)
| false -> Expr.PropertyGet(newex, propOrValInfo, args)
| ShapeVar var -> Expr.Var (var |> replaceVar)
| ShapeLambda (var, expr) -> Expr.Lambda(var |> replaceVar, substituteExpr expr)
| ShapeCombination(shapeComboObject, exprList) ->
RebuildShapeCombination(shapeComboObject, List.map substituteExpr exprList)
substituteExpr ex |> LeafExpressionConverter.QuotationToExpression
substitute<Record> (<# fun t -> t.A = 10 #>)
I suspect I've missed something in the substitution, but I'm stumped as to what.
The the .ToString() result of the substituted F# Expr is
Lambda (t,
Call (None, op_Equality,
[Coerce (PropertyGet (Some (t), Item, [Value ("A")]), Int32),
Value (10)]))
which looks correct. And other than the coersion, is the equivalent of <# fun (t: Dict) -> t["A"] = 10 #>.ToString()
Why is the QuotationToExpression failing ?
Every time you call replaceVar, you return a different instance of Var. So when you replace the lambda parameter, it's one instance of Var, and later, when you replace newex, that's another instance of Var.
Lambda (t, Call (None, op_Equality, [Coerce (PropertyGet (Some (t), ... ))
^ ^
| |
---------------------------------------------------------
These are different `t`, unrelated, despite the same name
To make this work, you have to make it the same t. The dumbest, most straightforward way would be this:
let substitute<'a> (ex: Expr<'a->bool>) =
let newArg = Var("arg", typeof<Dict>)
let replaceVar (v: Var) = if v.Type = typeof<'a> then newArg else v
...
This will make your particular example work as expected, but it is still unsound, because you're replacing not just specifically the lambda parameter, but any variable of the same type. Which means that if the expression happens to contain any variables of the same type as the parameter, you'd still hit the same problem. For example, try converting this:
<# fun t -> let z = { A = 15 } in z.A = 15 && t.A = 10 #>
You'll get a similar error, but this time complaining about variable z.
A better way would be to maintain a map of variable substitutions as you go, insert new variables as you encounter them for the first time, but get them from the map on subsequent encounters.
An alternative approach would be to fish out specifically the lambda parameter and then replace only it, rather than comparing variable types.
But then there's the next level of weirdness: you're converting any property accessor to an indexer accessor, but in my example above, z.A shouldn't be thus converted. So you have to somehow recognize whether the object of property access is in fact the argument, and that may not be as trivial.
If you're willing to settle for just the case of t.A and fail on more complicated cases like (if true then t else t).A, then you can just match on the lambda argument and pass through any other expression:
let substitute<'a> (ex: Expr<'a->bool>) =
let arg =
match ex with
| ShapeLambda (v, _) -> v
| _ -> failwith "This is not a lambda. Shouldn't happen."
let newArg = Var("arg", typeof<Dict>)
let replaceVar (v: Var) = if v = arg then newArg else v
let tEntityItem = typeof<Dict>.GetProperty("Item")
let isATypeShapeVar = function | ShapeVar var -> var.Type = typeof<'a> | _ -> false
let rec substituteExpr =
function
| PropertyGet(Some (ShapeVar a), propOrValInfo, c) when a = arg ->
let getter = Expr.PropertyGet(Expr.Var newArg, tEntityItem, [Expr.Value(propOrValInfo.Name)] )
Expr.Coerce(getter, propOrValInfo.PropertyType)
| ShapeVar var -> Expr.Var (var |> replaceVar)
| ShapeLambda (var, expr) -> Expr.Lambda(var |> replaceVar, substituteExpr expr)
| ShapeCombination(shapeComboObject, exprList) ->
RebuildShapeCombination(shapeComboObject, List.map substituteExpr exprList)
| ex -> ex
substituteExpr ex |> LeafExpressionConverter.QuotationToExpression
> substituteExpr <# fun t -> let z = { A = 15 } in z.A = 15 && t.A = 10 #>
val it: System.Linq.Expressions.Expression =
ToFSharpFunc(arg => z => ((z.A == 15) AndAlso (Convert(arg.get_Item("A"), Int32) == 10)).Invoke(new Record(15)))

FsCheck, I am not getting `Prop.forAll` to work (F#)

I am not coming right with FsCheck, when I try and use Prop.forAll.
I have created two tests to demonstrate what I am doing, expecting them both to fail.
type Data = { value: int }
type NeverAOne =
static member Data () =
Arb.generate<int>
|> Gen.filter (fun x -> x <> 1)
|> Gen.map (fun x -> { value = x })
|> Arb.fromGen
[<Property(Arbitrary = [| typeof<NeverAOne> |] )>] (* Fails *)
let ``Test One`` (x: Data) =
x.value = 1
[<Fact>]
let ``Test Two`` () = (* Passes *)
Prop.forAll (NeverAOne.Data ()) (fun x -> x.value = 1)
In this sample, Test Two passes. If I add breakpoints, I can see it is because no data is generated, so it iterates through 0 samples, which means none fail.
I am convinced that I am using Prop.forAll wrong, but though everything I have read through, I cannot find it.
If you mark the test as a plain Xunit Fact (rather than as a FsCheck Property), you have to explicitly check the property:
[<Fact>]
let ``Test Two`` () =
let prop = Prop.forAll (NeverAOne.Data ()) (fun x -> x.value = 1)
Check.QuickThrowOnFailure prop
The result I get is then:
System.Exception : Falsifiable, after 1 test (0 shrinks) (StdGen (74764374, 296947750)):
Original:
{ value = -2 }
Or you can just mark the test as a Property, of course:
[<Property>]
let ``Test Three`` () =
Prop.forAll (NeverAOne.Data ()) (fun x -> x.value = 1)

string representation of F# function signature

When I'm working in the F# REPL fsharpi whenever I enter a new function the signature is printed after I've entered them:
> let foo x = x;;
val foo : x:'a -> 'a
Is there a way to retrieve this as a string? The reason I'm asking is that I'm using IfSharp for Jupyter notebooks which doesn't display the signatures, but I'd like to be able to show the types of functions for demonstration purposes.
I've messed around a bit but can't get anything useful, I've tried:
let foo x = (x, x)
printfn "%A" (foo.GetType())
printfn "%A" foo
But this isn't quite what I need:
FSI_0013+clo#3-1
<fun:it#5-2>
Is it possible to access this at all?
AFAIK, there's no function in FSharp.Core for getting a type's string representation as it would appear to the compiler (though maybe there's something in FSharp.Compiler.Services -- I haven't checked). Here's a small function that works for most simple uses:
open System
let (|TFunc|_|) (typ: Type) =
if typ.IsGenericType && typ.GetGenericTypeDefinition () = typeof<int->int>.GetGenericTypeDefinition () then
match typ.GetGenericArguments() with
| [|targ1; targ2|] -> Some (targ1, targ2)
| _ -> None
else
None
let rec typeStr (typ: Type) =
match typ with
| TFunc (TFunc(_, _) as tfunc, t) -> sprintf "(%s) -> %s" (typeStr tfunc) (typeStr t)
| TFunc (t1, t2) -> sprintf "%s -> %s" (typeStr t1) (typeStr t2)
| typ when typ = typeof<int> -> "int"
| typ when typ = typeof<string> -> "string"
| typ when typ.IsGenericParameter -> sprintf "'%s" (string typ)
| typ -> string typ
typeStr typeof<(string -> (string -> int) -> int) -> int>
// val it: string = "string -> (string -> int) -> int"
typeStr (typeof<int->int>.GetGenericTypeDefinition())
// val it: string = "'T -> 'TResult"
You can easily write a function on top of this to use typeStr on a value's type:
let valTypeString x = typStr (x.GetType ())
You can analyze types representing F# functions, with the help of the Microsoft.FSharp.Reflection namespace. There is the caveat that generic function arguments default to System.Object, and that other F# types which may form incomplete patterns (e.g. union cases, records) are not included.
open Microsoft.FSharp.Reflection
let funString o =
let rec loop nested t =
if FSharpType.IsTuple t then
FSharpType.GetTupleElements t
|> Array.map (loop true)
|> String.concat " * "
elif FSharpType.IsFunction t then
let fs = if nested then sprintf "(%s -> %s)" else sprintf "%s -> %s"
let domain, range = FSharpType.GetFunctionElements t
fs (loop true domain) (loop false range)
else
t.FullName
loop false (o.GetType())
let foo x = x
funString foo
// val it : string = "System.Object -> System.Object"

Type mismatch error

Here is my code:
open System
let rec gcd a b =
match b with
| x when x = 0 -> a
| _ -> gcd(b, a % b)
let result = gcd 15 10
[<EntryPoint>]
let main(args : string[]) =
printfn "result = %d" result
0
Why I get the error with this code:
D:\datahub\Dropbox\development\myprojects\project-euler\Problem_5\problem_5.fs(6,16): error FS0001: Type mismatch. Expec
ting a
'a
but given a
int -> 'a
The resulting type would be infinite when unifying ''a' and 'int -> 'a'
The example tries to separate arguments by using a comma. In F# multiple arguments are supplied to a function by separating them with whitespace:
let rec gcd a b =
match b with
| x when x = 0 -> a
| _ -> gcd b (a % b)

Resources