I'm attempting to use Railway Oriented Programming principals http://fsharpforfunandprofit.com/rop/ and this http://indiedevspot.azurewebsites.net/2015/01/20/two-track-coding-rop-for-dummies-part-2/ for reference
I have successfully implemented this for most of the codebase, except now we are getting to putting items into SQL and wish to use ROP for validation of those types. The typical pattern is
Figure 1:
let createSomething a b c = {A = a; B = b; C = c}
let createValidSomething so =
createSomething
<!> validateFunction1 so.param1
<*> validateFunction2 so.param2
<*> ...so forth and so on
You will notice that createSomething is a function that returns a record type instantiation a -> b -> c -> a' -> b' -> c'
The SQL Type providers return a mutable type (non record). Lets look at my attempt to build a similar createSomething function
Figure 2:
let createSQS(a, b, c, d, e, f, g) =
let sqs = context.``[dbo].[Something]``.Create(a, b, c, d, e, f, g)
sqs
At this point, we know this already will not work, we have a->b->c->d->e->f->g->context.[dbo].[Something].Entity
I know I can have an intermediary record type and follow ROP principals, match on success/failure and then create my object off of the already validated. But does that not seem like too many steps?
Does anybody know of a good pattern for this? Ideally we could have a function similar to Figure1 that generates a Record Type that is compatible with the Type Providers.
I'm open to trying things and hanging out on Skype :).
Should your function createSQS not be better like this:
let createSQS a b c d e f g =
context.``[dbo].[Something]``.Create(a, b, c, d, e, f, g)
This one would have the needed signature of a->b->c->d->e->f->g->context.[dbo].[Something].Entity
So we came up with an answer at our dev meeting, and decided that we in fact WANT to execute each part in its own function. For the inner binds we invented our own operator; similar to plus (&&&) (which I will blog about on my site www.indiedevspot.com) and at the top level we ran with a normal bind.
Our top level code looks like this:
[<HttpPost>]
x.member Add(sa:Something) =
sa|>ValidateSomething
>>= converttoSSA
>>= persistSSA
We decided to separate the concerns due to independent testability of validation, conversion and persistence. The theory is that functional composition if made up of functions that are guaranteed to work, is itself inherently guaranteed to work (or have a much better chance).
If we went with the proposed method (which we have not yet solved), we would be mixing concerns of creation, validation and conversion. That would also end up creating an additional record type which was un-necessary.
Related
So, I'm an experienced OOP programmer (primarily C++), just now starting to dip my toes in with functional programming. From my understanding, in a purely functional paradigm, functions shouldn't have conditionals and should be broken down as much as possible using currying. Could someone provide me the "pure" functional version of the following example? Preferably using every strict technique that would be part of the functional paradigm:
let rec greatestCommonFactor a b =
if a = 0 then b
elif a < b then greatestCommonFactor a (b - a)
else greatestCommonFactor (a - b) b
The example function that you have supplied is already purely functional. When we talk about a function purity, what we are actually talking about is the property of functions being referentially transparent.
An expression is referentially transparent if it can be replaced with its value without altering the effect of the program. To give a simple example, imagine the function:
let add2 x = x + 2
Now, anywhere that the value add2 2 appears in our program, we can substitute the value 4 without altering the behaviour of the program.
Imagine now that we add some additional behaviour into the function that prints to the console:
let add2Print x =
printfn "%d" x
x + 2
Although the result of the function is the same as before, we can no longer perform value substitution with the value 4 without changing the behaviour of our program because our function has the additional side-effect of printing to the console.
This function is no longer referentially transparent and therefore not a pure function.
let rec greatestCommonFactor a b =
if a = 0 then b
elif a < b then greatestCommonFactor a (b - a)
else greatestCommonFactor (a - b) b
Looking at this function that you have supplied, no side-effects are involved in its execution. We will always get the same output value for given inputs a and b, therefore this is already a pure function.
To be clear, there is absolutely no issue with functions containing conditionals in functional programming. Often, however, we make use of pattern matching rather than if/elif/else expressions but in the example you have described, this is purely stylistic. An alternative expression of your function using pattern matching would be:
let rec greatestCommonFactor a b =
match a with
|0 -> b
|a' when a' < b -> greatestCommonFactor a' (b - a')
|a' -> greatestCommonFactor (a' - b) b
I have a general function that takes a lot of parameters
f : a -> b -> c -> d -> e -> f
I want to provide specialized functions that only take the last two parameters, but provide some fixed values for the first three.
g : d -> e -> f
h : d -> e -> f
Their implementation is something like the following
g = f someA someB someC
h = f someA' someB' someC'
This is all great of course, but when it comes to invoking those functions from C# it's a problem because their types don't get "prettified". Instead I get a bunch of nested FSharpFuncs.
I can avoid this problem by defining my functions like
g d e = f someA someB someC d e
h d e = f someA' someB' someC' d e
But this seems like a really simple, mechanical transformation so I'm wondering if there's an automated way to get the same result. Perhaps some attribute I can attach to them?
Technically speaking, the first and second options of how to write your g and h are not exactly the same. In the first case, f is applied to three arguments and the resulting new function is stored as an object in the value g.
Whereas in the second case, the function f is called with all 5 arguments every time with the values of someA, someB and someC being passed at the time of calling g.
For most cases, this distinction is not really relevant, but it becomes important when you want to cache some parts of your computation.
Long story short: The transformation has a slight semantic difference and therefore cannot really be done automatically. Just add the arguments to the new g and h.
I don't understand how the Value Restriction in F# works. I've read the explanation in the wiki as well as the MSDN documentation. What I don't understand is:
Why, for example, this gives me a Value Restriction error (Taken from this question):
let toleq (e:float<_>) a b = (abs ( a - b ) ) < e
But ths doesn't:
let toleq e (a:float<_>) b = (abs ( a - b ) ) < e
This is generalized all right...
let is_bigger a b = a < b
but this isn't (it is specified as int):
let add a b = a + b
Why functions with implicit parameters generate Value Restriction:
this:
let item_count = List.fold (fun acc _ -> 1 + acc) 0
vs this:
let item_count l = List.fold (fun acc _ -> 1 + acc) 0 l
(Mind you, if I do use this function in a code fragment the VR error will be gone, but then the function will be specified to the type I used it for, and I want it to be generalized)
How does it work?
(I'm using the latest F#, v1.9.6.16)
EDIT
Better/recent info is here: Keeping partially applied function generic
(original below)
I think a pragmatic thing here is not to try to understand this too deeply, but rather to know a couple general strategies to get past the VR and move on with your work. It's a bit of a 'cop out' answer, but I'm not sure it makes sense to spend time understanding the intracacies of the F# type system (which continues to change in minor ways from release to release) here.
The two main strategies I would advocate are these. First, if you're defining a value with a function type (type with an arrow '->'), then ensure it is a syntactic function by doing eta-conversion:
// function that looks like a value, problem
let tupleList = List.map (fun x -> x,x)
// make it a syntactic function by adding argument to both sides
let tupleList l = List.map (fun x -> x,x) l
Second, if you still encounter VR/generalizing problems, then specify the entire type signature to say what you want (and then 'back off' as F# allows):
// below has a problem...
let toleq (e:float<_>) a b = (abs ( a - b ) ) < e
// so be fully explicit, get it working...
let toleq<[<Measure>]'u> (e:float<'u>) (a:float<'u>) (b:float<'u>) : bool =
(abs ( a - b ) ) < e
// then can experiment with removing annotations one-by-one...
let toleq<[<Measure>]'u> e (a:float<'u>) b = (abs ( a - b ) ) < e
I think those two strategies are the best pragmatic advice. That said, here's my attempt to answer your specific questions.
I don't know.
'>' is a fully generic function ('a -> 'a -> bool) which works for all types, and thus is_bigger generalizes. On the other-hand, '+' is an 'inline' function which works on a handful of primitive types and a certain class of other types; it can only be generalized inside other 'inline' functions, otherwise it must be pinned down to a specific type (or will default to 'int'). (The 'inline' method of ad-hoc polymorphism is how the mathematical operators in F# overcome the lack of "type classes".)
This is the 'syntactic function' issue I discussed above; 'let's compile down into fields/properties which, unlike functions, cannot be generic. So if you want it to be generic, make it a function. (See also this question for another exception to this rule.)
Value restriction was introduced to address some issues with polymorphism in the presence of side effects. F# inherits this from OCaml, and I believe value restriction exists in all ML variants. Here's a few more links for you to read, besides the links you cited. Since Haskell is pure, it's not subjected to this restriction.
As for your questions, I think question 3 is truly related to value restriction, while the first two are not.
No one, including the people on the F# team, knows the answer to this question in any meaningful way.
The F# type inference system is exactly like VB6 grammar in the sense that the compiler defines the truth.
Unfortunate, but true.
I want to apply a function to both members of a homogenous tuple, resulting in another tuple. Following on from my previous question I defined an operator that seemed to make sense to me:
let (||>>) (a,b) f = f a, f b
However, again I feel like this might be a common use case but couldn't find it in the standard library. Does it exist?
I don't think there is any standard library function that does this.
My personal preference would be to avoid too many custom operators (they make code shorter, but they make it harder to read for people who have not seen the definition before). Applying function to both elements of a tuple is logically close to the map operation on lists (which applies a function to all elements of a list), so I would probably define Tuple2.map:
module Tuple2 =
let map f (a, b) = (f a, f b)
Then you can use the function quite nicely with pipelining:
let nums = (1, 2)
nums |> Tuple2.map (fun x -> x + 1)
Suppose I have the following DU:
type Something =
| A of int
| B of string * int
Now I use it in a function like this:
let UseSomething = function
| A(i) -> DoSomethingWithA i
| B(s, i) -> DoSomethingWithB s i
That works, but I've had to deconstruct the DU in order to pass it to the DoSomethingWith* functions. It feels natural to me to try to define DoSomethingWithA as:
let DoSomethingWithA (a: Something.A) = ....
but the compiler complains that the type A is not defined.
It seems entirely in keeping with the philosophy of F# to want to restrict the argument to being a Something.A, not just any old int, so am I just going about it the wrong way?
The important thing to note is that A and B are constructors of the same type Something. So you will get inexhaustive pattern matching warning if you try to use A and B cases separately.
IMO, deconstructing all cases of DUs is a good idea since it is type-safe and forces you to think of handling those cases even you don't want to. The problem may arise if you have to deconstruct DUs repetitively in the same way. In that case, defining map and fold functions on DUs might be a good idea:
let mapSomething fa fb = function
| A(i) -> fa i
| B(s, i) -> fb s i
Please refer to excellent Catamorphism series by #Brian to learn about fold on DUs.
That also said that your example is fine. What you really process are string and int values after deconstruction.
You can use Active Patterns to consume two cases separately:
let (|ACase|) = function A i -> i | B _ -> failwith "Unexpected pattern B _"
let (|BCase|) = function B(s, i) -> (s, i) | A _ -> failwith "Unexpected pattern A _"
let doSomethingWithA (ACase i) = ....
but inferred type of doSomethingWithA is still the same and you get an exception when passing B _ to the function. So it's a wrong thing to do IMO.
The other answers are accurate: in F# A and B are constructors, not types, and this is the traditional approach taken by strongly typed functional languages like Haskell or the other languages in the ML family. However, there are other approaches - I believe that in Scala, for example, A and B would actually be subclasses of Something, so you could use those more specific types where it makes sense to do so. I'm not completely sure what tradeoffs are involved in the design decision, but generally speaking inheritance makes type inference harder/impossible (and true to the stereotype type inference in Scala is much worse than in Haskell or the ML languages).
A is not a type, it is just a constructor for Something. There's no way you can avoid pattern matching, which is not necessarily a bad thing.
That said, F# does offer a thing called active patterns, for instance
let (|AA|) = function
| A i -> i
| B _ -> invalidArg "B" "B's not allowed!"
which you can then use like this:
let DoSomethingWithA (AA i) = i + 1
But there's no real reason why you would want to do that! You still do the same old pattern matching under the hood, plus you risk the chance of a runtime error.
In any case, your implementation of UseSomething is perfectly natural for F#.