Can someone check my sanity here please. Given this simple function:
let filterOut item l =
l |> List.filter (fun t -> not (t = item))
let f =
["1";"2";"3"]
|> filterOut "3"
Evaluating the above in FSI produces the following:
Xamarin Studio with mono 4.0.3 on Mac OS X
val f : string list = ["1"]
Visual Studio 2013
val f : string list = ["1"; "2"]
If the input is a list of ints or chars - then it works as expected and both platforms produce identical results. Also if I specify filterOut to only work with strings it correctly produces identical values. Like so:
let filterOut item l:list<string> =
l |> List.filter (fun t -> not (t = item))
Even the following code with XS on OS X:
let filterOut item l =
l |> List.filter (fun t -> not (t = item))
let f =
["1";"2";"3"]
|> filterOut "foobar"
outputs:
val f : string list = ["1"]
I have compared the IL between the XS and VS compiled code and they appear identical. So it seems like a runtime discrepancy.
If there something going on here with List.Filter and generic comparison with strings on Mono?
EDIT: If I add "inline" to the filterOut function I also get correct results on both platforms (expected output on OS X). Again it seems something is wrong with the generic comparer on the Mono runtime.
(1 month later) Tested on latest Mono 4.2.0 and now works as expected.
Related
How to resolve this problem with type inference?
open Microsoft.FSharp.Linq.RuntimeHelpers
open System
open System.Linq.Expressions
open Accord.Math.Optimization
module Vector=
let compareScalarProcut(a:double[])(b:double[])(greaterOrEqualThen:float)=
Array.map2 (*) a b
|> Array.sum
|> fun x-> x >= greaterOrEqualThen
module Lambda =
let toExpression (``f# lambda`` : Quotations.Expr<'a>) =
``f# lambda``
|> LeafExpressionConverter.QuotationToExpression
|> unbox<Expression<'a>>
let LambdaExpression (coefficients:double[]) =
<# Func<double[], bool>(fun i -> (Vector.compareScalarProcut(i,coefficients,0)) #>
|> Lambda.toExpression
You're calling your function incorrectly. It's a "normal" F# function that takes arguments separated by whitespace, instead of a tuple of arguments separated by commas. Try this instead:
Vector.compareScalarProcut i coefficients 0.0
I wrote an FsCheck generator that yields random glob syntax patterns (e.g. a*c?) along with a random string that matches the pattern (e.g. abcd). However my solution uses a mutable variable and I'm rather ashamed of that. Have a look:
open FsCheck
type TestData = {Pattern: string; Text: string}
let stringFrom alphabet =
alphabet |> Gen.elements |> Gen.listOf |> Gen.map (List.map string >> List.fold (+) "")
let singleCharStringFrom alphabet =
alphabet |> Gen.elements |> Gen.map string
let matchingTextAndPatternCombo = gen {
let toGen = function
| '*' -> stringFrom ['a'..'f']
| '?' -> singleCharStringFrom ['a'..'f']
| c -> c |> string |> Gen.constant
let! pattern = stringFrom (['a'..'c']#['?'; '*'])
let mutable text = ""
for gen in Seq.map toGen pattern do
let! textPart = gen
text <- text + textPart
return {Pattern = pattern; Text = text}
}
Notice that text is mutable and how its value is accumulated in a loop.
My guts tell me that there must be a way to fold the generators into text, but I can't figure how, because I don't understand how let! works under the hood (yet). I was considering something similar to the following:
let! text = pattern |> Seq.map toGen |> Seq.fold (?) (Gen.constant "")
Am I on the right track? What should the accumulator and seed for fold look like?
Your intuition that something like fold could be used here is right, but the problem is that you'd need a version of fold where the folding function returns Gen<'T> computation - so normal List.fold from F# will not work. In this case, I think using mutation is perfectly fine - your code looks pretty clear to me.
Looking through the functions in the Gen module, I do not see a version of fold, but I think Gen.sequence lets you do what you need nicely:
let! textParts = Gen.sequence (Seq.map toGen pattern)
let text = String.concat "" textParts
The Gen.sequence function takes a list of generators and returns a generator that generates a list of values using those generators - this way, you can generate all text parts at once and then just concatentate the results.
If you wanted to write your own fold and use that, it would look something
like this:
let rec fold f init xs = gen {
match xs with
| [] -> return init
| x::xs ->
let! state = f init x
return! fold f state xs }
The code to fold generators would then be:
let! text =
Seq.map toGen pattern |> List.ofSeq |> fold (fun (text:string) g -> gen {
let! textPart = g
return text + textPart }) ""
I have not tested this, so there may be bugs (most likely, it folds the wrong way round and so you'll end up with reversed strings), but the general structure should be right.
I know there's the back-pipe (<|) operator, referenced in several other SO answers. But that doesn't work well when combined with forward pipes (|>), which is common in chaining. However I'm looking for related options. Basically is there any built-in version of the below function definition? Or is this a bad/dangerous practice?
let inline (^%) f = f
let stuff =
[1;2;3]
|> Seq.filter ^% (>) 2
|> Seq.map ^% fun x -> x.ToString()
// compare to this, which doesn't compile (and would be hard to follow even if it did)
let stuff =
[1;2;3]
|> Seq.filter <| (>) 2
|> Seq.map <| fun x -> x.ToString()
There are some Haskell features, like optional infixing using backticks, and sections, which aren't available in F#. That makes certain constructs a bit more verbose.
Usually, I'd simply write a pipe of functions as the above like this:
let stuff =
[1;2;3]
|> Seq.filter (fun x -> x < 2)
|> Seq.map string
This is, in my opinion, much more readable. For example, using Seq.filter ^% (>) 2, I'd intuitively read that as meaning 'all values greater than 2', but that's not what it does:
> let inline (^%) f = f;;
val inline ( ^% ) : f:'a -> 'a
> let stuff =
[1;2;3]
|> Seq.filter ^% (>) 2
|> Seq.map ^% fun x -> x.ToString()
|> Seq.toList;;
val stuff : string list = ["1"]
If you leave the reader of the code in doubt of what the code does, you've just made everyone less productive. Using Seq.filter (fun x -> x < 2) may look more verbose, but is unambiguous to the reader.
Trying to learning F# and I tried to reimplement the following function in F#
private string[] GetSynonyms(string synonyms)
{
var items = Enumerable.Repeat(synonyms, 1)
.Where(s => s != null)
.Select(XDocument.Parse)
.Select(doc => doc.Root)
.Where(root => root != null)
.SelectMany(e => e.Elements(SynonymsNamespace + "synonym"))
.Select(e => e.Value)
.ToArray();
return items;
}
I got this far by myself
let xname = XNamespace.Get "http://localuri"
let syn = "<synonyms xmlns=\"http://localuri\"><synonym>a word</synonym><synonym>another word</synonym></synonyms>"
let synonyms str =
let items = [str]
items
|> List.map System.Xml.Linq.XDocument.Parse
|> List.map (fun x -> x.Root)
|> List.map (fun x -> x.Elements(xname + "synonym") |> Seq.cast<System.Xml.Linq.XElement>)
|> Seq.collect (fun x -> x)
|> Seq.map (fun x -> x.Value)
let a = synonyms syn
Dump a
Now I'm wondering if there is a more-functional way to write the same code.
By extracting the access to the properties to standalone functions I got this version
let xname = XNamespace.Get "http://localuri"
let syn = "<synonyms xmlns=\"http://localuri\"><synonym>a word</synonym><synonym>another word</synonym></synonyms>"
let getRoot (doc:System.Xml.Linq.XDocument) = doc.Root
let getValue (element:System.Xml.Linq.XElement) = element.Value
let getElements (element:System.Xml.Linq.XElement) =
element.Elements(xname + "synonym")
|> Seq.cast<System.Xml.Linq.XElement>
let synonyms str =
let items = [str]
items
|> List.map System.Xml.Linq.XDocument.Parse
|> List.map getRoot
|> List.map getElements
|> Seq.collect (fun x -> x)
|> Seq.map getValue
let a = synonyms syn
Dump a
But I still have a few concerns
Can I rewrite that Seq.collect (fun x -> x) in another way? It sounds redundant
Can I remove all those (fun x -> x.Property) without creating new functions?
How to actually return an array and not a Seq<'a> (which I understand is an IEnumerable<'a>)
Thanks
Seq.collect (fun x -> x) can be rewritten with the predefined id function to Seq.collect id
In F# 4.0 it can be removed for constructors only.
use Seq.toArray or Seq.toList
Would it be very wrong to drop the C#-code and go all in with the XML-provider in F#? In my world its always wrong to parse XML when there exists other solutions (unless Im trying to create octogonal wheels or moist gun powders other have made better before me).
In this regard I would even have used some transformation (XSLT) or selection (XPATH/XQUERY) unless I could use the XML-provider or some XSD (c#) for generating code.
If for some reason the XML is so unstructured that you actually need parsing, then the XML is arguably wrong...
If using the XmlProvider you get namespacing, types etc for free...
#r #"..\correct\this\path\to\packages\FSharp.Data.2.2.5\lib\net40\FSharp.Data.dll"
#r "System.Xml.Linq"
open FSharp.Data
[<Literal>]
let syn = "<synonyms xmlns=\"http://localuri\"><synonym>a word</synonym><synonym>another word</synonym></synonyms>"
type Synonyms = XmlProvider<syn>
let a = Synonyms.GetSample()
a.Synonyms |> Seq.iter (printfn "%A")
Mind that the XmlProvider also can take files or url as examples for inferring types etc, and that you also can have this code as the example and then use
let a = Synonyms.Load(stuff)
where stuff is a read from stream, textreader or URI and inferred according to your example. The sample and the stuff might even point to same file/Uri if this is some standard placing of data.
See also: http://fsharp.github.io/FSharp.Data/library/XmlProvider.html
Usually, when I need to build a list from 0 to 10, I simply do this: [0..10]. This gives me a list of integers from 0 to 10. But this time I would need a list of float from 0 to 10. Is there a way to do that?
let testFunc (x: float<metre>) =
x
let otherTestFunc =
[0.0 .. 10.0] // How do I make this return float<metre>
|> List.map (fun x -> testFunc x)
I reported this to the F# team a while ago, but you need to specify the step manually when using Measures.
let testFunc (x: float<metre>) =
x
let otherTestFunc =
[0.0 <metre> .. 1.0<metre> .. 10.0 <metre>] // How do I make this return float<metre>
|> List.map (fun x -> testFunc x)
Floating-point loops may be dangerous as they hide an accumulating round-off error. See F# Floating point ranges are experimental and may be deprecated for more details.
I believe, the easiest way is to keep your loop in a plain, non-measured int, and convert the value within the loop.
let otherTestFunc =
[0 .. 10]
|> List.map (float >> (*) 1.0<metre>)
|> List.map testFunc