F# LazyList -> IList - f#

I'm creating a module that will be used by C# code, so I would rather not return the LazyList<> directly. If I did, the C# would have to reference the FSharp.PowerPack, which seems strange.
So I would rather return a IList<>, but when I try to do something like:
let x = LazyList.ofSeq {0..10}
let y = x :> IList<int32>
However, this gives me the error:
The type 'LazyList<int> is not compatible with the type 'IList<int>'
This leads me to believe that LazyList<> does NOT implement IList<>. Is this true?
What am I missing?

It is true, LazyList does not implement the IList interface. It implements IEnumerable though.
[<Sealed>]
type LazyList<'T> =
interface IEnumerable<'T>
interface System.Collections.IEnumerable

Related

How to use Akka.Streams.*.ConcatMany in F#?

I want to create a flow that creates a new source (it will be a persistence query) out of incoming elements, and then flattens the results. Something like this simplified example:
var z = Source.Single(1).ConcatMany(i => Source.Single(i));
this code compiles and works as expected. My problem is that when I translate it to F#:
let z = Source.Single(1).ConcatMany(fun i -> Source.Single(i))
I get an error saying
This expression was expected to have type
'IGraph<SourceShape<'a>,Akka.NotUsed>'
but here has type
'Source<int,Akka.NotUsed>'
I think that the cause of that is that F# handles co/contravariance differently than C# and cannot simply convert these generic specializations (https://github.com/fsharp/fslang-suggestions/issues/162), but I cannot figure out a way to make a convertion between an int and a SourceShape<int>. Is it possible to convert this example to F#?
Looking at the code on GitHub, it appears that Source<TOut, TMat> is a direct implementation of IGraph, so you should just be able to cast it:
public sealed class Source<TOut, TMat> : IFlow<TOut, TMat>, IGraph<SourceShape<TOut>, TMat>
let z = Source.Single(1).ConcatMany(fun i -> Source.Single(i) :> IGraph<SourceShape<int>,Akka.NotUsed>)
I think the biggest difference between the C# and F# usage is that C# will automatically do the upcast for you.
One workaround that I found is to use Akkling.Streams wrapper library:
open Akkling.Streams
let x =
Source.singleton 1
|> Source.collectMap(fun x -> Source.singleton x)
the question how to do this without Akkling remains open.

NancyFx F# App with parameter

I am trying to get this example translated from C# to F#
public class MyModule : NancyModule
{
private IMyDependency _dependency;
public MyModule(IMyDependency dependency)
{
_dependency = dependency;
Get["/"] = x =>
{
};
// Register other routes
}
}
(source 1)
However adding a parameter to constructor
type HelloModule(dependency) as self =
inherit NancyModule()
do
self.Get.["/"] <- fun _ -> "Hello" :> obj
(source 2)
results in a run-time exception: System.InvalidOperationException: 'Something went wrong when trying to satisfy one of the dependencies during composition ...
How can I correctly add a dependency like a data-source to the code? Or, generally, how do I pass something from outside of HelloModule to the inside?
I'm guessing this might be caused by not specifying the type of the dependency parameter of the constructor in your F# code. This would result in the F# compiler assigning that parameter a generic type, and then Nancy's dependency injection framework doesn't know what to inject.
Try the following and see if it fixes your problem:
type HelloModule(dependency : IMyDependency) as self =
inherit NancyModule()
do
self.Get.["/"] <- fun _ -> "Hello" :> obj
P.S. Naturally, for this to work, you'll also need to have some type that implements the IMyDependency interface, and have told the Nancy framework about that type. From this part of the Nancy documentation that you linked to, it looks like merely declaring the type is enough, but if that's not actually enough then you'll have to register the type manually. I'm not familiar enough with Nancy to give you specific advice there beyond what the documentation says.

f# type providers and INPC metaprogramming

I read the following article
http://studentguru.gr/b/kron/archive/2012/09/26/c-template-metaprogramming-and-f-type-providers.aspx
which shows a way to do compile time Fibonacci sequence generation with F# Type providers. The solution is in the article but the final program is
> cat .\fib.fs
type fib = Playground.StaticFibonacci<100000>
printfn "Fibonacci(100000) has %d digits" fib.Value.Length
> fsc .\fib.fs -o fib.exe -r:.\FibonacciTypeProvider.dll –nologo
> .\fib.exe
Fibonacci(100000) has 20899 digits
This look very powerful. I was wondering if it would be possible to create a type provider for INPC ( INotifyPropertyChanged ) such that you instead of
open System.ComponentModel
type MyObject() =
let mutable propval = 0.0
let propertyChanged = Event<_, _>()
interface INotifyPropertyChanged with
[<clievent>]
member x.PropertyChanged = propertyChanged.Publish
member this.MyProperty
with get() = propval
and set(v) =
propval <- v
propertyChanged.Trigger(this, new PropertyChangedEventArgs("MyProperty"))
You might be able to write
open System.ComponentModel
type MyObject() =
let mutable propval = 0.0
let propertyChanged = Event<_, _>()
interface INotifyPropertyChanged with
[<clievent>]
member x.PropertyChanged = propertyChanged.Publish
member this.MyProperty : INPCTypeProvider<double>
So before I waste half a day digging into this perhaps somebody more informed could tell me I am wasting my time and this level of meta programming is just not possible.
I do not think you can achieve this with F# type providers (but I can see that that it would be nice). There is a number of problems and thoughts I can think of:
In your example, your INPCTypeProvider<double> would have to return something like a representation of a "property". This is not possible, because properties are not first-class values (unlike events). If they were, you wouldn't need a type provider...
Type provider cannot be parameterized by an existing type, so you cannot write say:
type MyNotifyObject = ProvideNotifiable<MyObject>
If this was possible, ProvideNotifiable could be a provider taking a type and building a new type with additional interface implementation. But this is not possible at the moment.
If you only need simple types, you might be able to create something like:
type MyObject = ProvideNotifiable<"MyProperty:int, OtherProperty:string">
This could generate a type with the two properties (defined in the string), but you cannot add anything more to the generated type (although, you might be able to generate actual type using generative provider and inherit from it...) I think this is probably the best you can do.
Aside from type providers, you can simplify the implementation of INotifyPropertyChanged a bit by using quotations. This F# snippet gives a simple example that makes the implementation safer.

why is the implementation of my abstract member not public

I've been struggling to get this to compile for about an hour. It must be something stupid. Can you spot it?
in my lib project:
namespace TravelerStuff
open System
type Traveler =
abstract GetData : unit -> unit
type public DeltaTraveler() =
interface Traveler with
member v.GetData () =
printf "hello"
and in my console test app:
[<EntryPoint>] let main _ =
let traveler = new TravelerStuff.DeltaTraveler()
traveler.GetData // this line won't compile: (The field, constructor or member 'GetData' is not defined)
As gradbot says, F# doesn't currently implicitly convert values to interfaces when searching for members. Also, F# only uses explicit interface implementation (as known from C#) and not implicit implementation where members are not only compiled as implementation of an interface, but also as ordinary (directly visible) members of the type.
Aside from casting, you can duplicate the member in the type definition:
type DeltaTraveler() =
member v.GetData () = printf "hello"
interface Traveler with
member v.GetData () = v.GetData()
Also, if you just want to implement an interface, but don't need to add any members, you can use F# object expressions (which are more lightweight):
let deltaTraveler() =
{ new Traveler with
member v.GetData () = printf "hello" }
// The function directly returns value of type 'Traveler'
let t = deltaTraveler()
t.GetData()
You need to upcast. F# currently won't do it for you in this situation.
(traveler :> TravelerStuff.Traveler).GetData()
// open the namespace to reduce typing.
open TravelerStuff
(traveler :> Traveler).GetData()
Snip from F# docs.
In many object-oriented languages,
upcasting is implicit; in F#, the
rules are slightly different.
Upcasting is applied automatically
when you pass arguments to methods on
an object type. However, for let-bound
functions in a module, upcasting is
not automatic, unless the parameter
type is declared as a flexible type.
For more information, see Flexible Types (F#).

How do you use (get values from keys, add items) Hashtables in F#

I would like to know how to use a System.Collections.Hashtable in F#. The reason it is a Hashtable is because I am referencing C# assemblies.
How would I call the following methods?
- Add
- Get value from key
I have not been able to find anything useful in Google about this.
As Mark points out, you can work with the Hashtable type directly from F# (just like with any other .NET type). The syntax for accessing indexers in F# is slightly different though:
open System.Collections
// 'new' is optional, but I would use it here
let ht = new Hashtable()
// Adding element can be done using the C#-like syntax
ht.Add(1, "One")
// To call the indexer, you would use similar syntax as in C#
// with the exception that there needst to be a '.' (dot)
let sObj = ht.[1]
Since Hashtable is not generic, you would probably want to cast the object back to string. To do that, you can either use the :?> downcast operator, or you can use the unbox keyword and provide a type annotation to specify what type do you want to get as the result:
let s = (sObj :?> string)
let (s:string) = unbox sObj
If you have any control over what type is used, then I would recommend using Dictionary<int, string> instead of Hashtable. This is fully compatible with C# and you would avoid the need to do casting. If you're returning this as a result from F#, you could also use standard F# map and just upcast it to IDictionary<_,_> before passing it to C#:
let map = Map.empty |> Map.add 1 "one"
let res = map :> IDictionary<_, _>
This way, C# users will see a familiar type, but you can write the code in the usual functional style.
It's pretty straightforward to do.
open System.Collections //using System.Collections
let ht = Hashtable() // var ht = new Hashtable()
ht.Add(1, "One")
let getValue = ht.Item[1] // var getValue = ht[1];
//NB: All indexer properties are named "Item" in F#.

Resources