Can I always replace do ... pure ... with ado ... in ... in Purescript? - typeclass

Can I always replace a do-block like this:
do
...
pure ...
where the last line is "pure" something,
with an ado-block like this:
ado
...
in ...
?
I know do only requires Bind and not Monad (i.e. Applicative), but we're already using pure so we're already Applicative.

The long answer
The difference between Applicative (and therefore applicative do - ado) and Monad (bind or do) is that when combining two applicative computations, the second one cannot depend on the result of the first computation. This means:
do
x <- getX
y <- getY
pure { x, y }
-- Can be turned into
ado
x <- getX
y <- getY
in { x, y }
But if y depends on x we cannot do that:
do
x <- getX
y <- getY x
pure { x, y }
-- This won't compile
ado
x <- getX
y <- getY x
in { x, y }
This means the answer to your question is "no".
Examples
Let's think about an intuitive example. The Aff Monad allows us to run asynchronous effects, like fetching data from an API. If the requests are independent, we can run them in parallel.
ado
user1 <- get "/user/1"
user2 <- get "/user/2"
in [user1, user2]
If they depend on each other, we need to run one request after another:
do
user1 <- get "/user/1"
bestFriend <- get ("/user/" <> user1.bestFriendId)
pure { user1, bestFriend }
Please note, that Aff always runs things sequentially no matter if you use bind or apply, unless we use parallel which turns an Aff into a ParAff. Notice the lack of a Bind/Monad instance for ParAff because two parallel computations cannot depend on each others results! https://pursuit.purescript.org/packages/purescript-aff/7.1.0/docs/Effect.Aff#t:ParAff
Meaning for the first example to really run in parallel, we have to actually
ado
user1 <- parallel $ get "/user/1"
user2 <- parallel $ get "/user/2"
in [user1, user2]
Another example I like is parsing/validation. Imagine you are parsing two fields of user input: A date string and an age. We can check both properties an parallel and return two errors if both properties are invalid. But to validate a date, we might first have to check if an input value is a string and then check if the value is a date string. For an example library, check out purescript-foreign
validated = ado
date <- do
str <- isString dateInput
isDate date
age <- do
int <- isInt ageInput
isPositive int
in { date, age }
We see that Applicative is much weaker than Monad. But there are intances, where forgoing in the power of Monad can give us other interesting possibilities like parallelisation or multiple errors.

Related

Parse Error: (incorrect indentation or misplaced bracket)

I'm starting out to learn Haskell. Even though I'm a dunce extraordinaire, I am intent on making this work. The error I received is listed as the title. This is the code that I wrote to try to implement the behavior of replicating a list (n) times and concatenating its new length as a new list. Now I have a basic understanding of how parsing works in Haskell, below my original code I will give example of some modified code to see if my understanding on parsing is adequate. My question for now is how I can properly indent or structure my block in order to not receive this error (is that specific enough :O) -- is there a piece of information I'm missing when it comes to creating instances and formatting? PLEASE DO NOT TELL ME OR OFFER SUGGESTIONS IF YOU NOTICE THAT MY CURRENT INSTANCE OR MAIN FUNCTION ARE SYNTACTICALLY WRONG. I want to figure it out and will deal with that GHC error when I get to it. (I hope that's the proper way to learn). BUT if I could ask for anyone's help in getting past this first obstacle in understanding proper formatting, I'd be grateful.
module Main where
import Data.List
n :: Int
x :: [Char]
instance Data stutter n x where
x = []
n = replicate >>= x : (n:xs)
stutter >>= main = concat [x:xs]
let stutter 6 "Iwannabehere" -- <-- parse error occurs here!!!
--Modified code with appropriate brackets, at least where I think they go.
module Main where
import Data.List
n :: Int
x :: [Char]
instance Data stutter n x where{
;x = []
;n = replicate >>= x : (n:xs)
;stutter >>= main = concat [x:xs]
;
};let stutter 6 "Iwannabehere" -- there should be no bracket of any kind at the end of this
I placed the 'let' expression on the outside of the block, I don't believe it goes inside and I also receive a parsing error if I do that. Not correct but I thought I'd ask anyway.
I'm not sure what the instance Data stutter n x is supposed to be, the instance XYZ where syntax is used solely for typeclasses, but you have a couple syntax errors here.
First of all, while GHC says that the error is on let stutter 6 "Iwannabehere", your first error occurs before that with stutter >>= main = concat [x:xs]. A single = sign is reserved for assignments, which are merely definitions. You can have assignments at the top level, inside a where block, or inside a let block (the where includes typeclass instance definitions). You can't have an assignment be part of an expression like x >>= y = z.
Your next syntax error is the let itself. let blocks can not appear at the top level, they only appear within another definition. You use let in GHCi but the reasons for that are outside the scope of this answer. Suffice to say that entering expression in GHCi is not equivalent to the top level of a source file.
Next, if you were to use a let block somewhere, it can only contain definitions. The syntax looks more like
let <name> [<args>] = <definition>
[<name> [<args>] = <definition>]
in <expression>
And this whole block makes an expression. For example, you could write
def f(x, y, z):
w = x + y + z
u = x - y - z
return w * u
in Python, and this would be equivalent to the Haskell function definition
f x y z = let w = x + y + z
u = x - y - z
in w * u
It only defines local variables. There is another form when you're using it inside do blocks where you can exclude the in <expression> part, such as
main = do
name <- getLine
let message = if length name > 5 then "short name" else "long name"
goodbye n = putStrLn ("Goodbye, " ++ n)
putStrLn message
goodbye name
Note that there is no need to use in here. You can if you want, it just means you have to start a new do block:
main = do
name <- getLine
let message = ...
goodbye n = ...
in do
putStrLn message
goodbye name
And this isn't as pretty.
Hopefully this points you more towards correct syntax, but it looks like you have some misunderstandings about how Haskell works. Have you looked at Learn You a Haskell? It's a pretty gentle and fun introduction to the language that can really help you learn the syntax and core ideas.
Your parse error is from the let keyword. Remove it and no error related to that will occur. let x = y is only relevant in GHCi and do-blocks, neither of which is relevant at this point. Essentially, just replace it with this line:
theWordIGet = stutter 6 "Iwannabehere"
Secondly, instance keyword in Haskell has absolutley nothing to do with what you want to do at this stage. This is not how Haskell functions are defined, which is what I'm guessing you want to do. This is what you're wanting to do to create a stutter function, assuming it simply repeats a string n times.
stutter :: Int -> String -> String
stutter n x = concat (replicate n x)
You'll also want to remove the type declarations for the (out-of-scope) values n and x: they're not objects, they're arguments for a function, which has its own signature determining the types of n and x within a function call.
Lastly, I imagine you will want to print the value of stutter 6 "Iwannabehere" when the program is executed. To do that, just add this:
main :: IO ()
main = print (stutter 6 "Iwannabehere")
In conclusion, I implore you to start from scratch and read 'Learn You a Haskell' online here, because you're going off in entirely the wrong direction - the program you've quoted is a jumble of expressions that could have a meaning, but are in the wrong place entirely. The book will show you the syntax of Haskell much better that I can write about in this one answer, and will explain fully how to make your program behave in the way you expect.

What's the most "functional" way to select a subset from this array?

I'd like to get more comfortable with functional programming, and the first educational task I've set myself is converting a program that computes audio frequencies from C# to F#. The meat of the original application is a big "for" loop that selects a subset of the values in a large array; which values are taken depends on the last accepted value and a ranked list of the values seen since then. There are a few variables that persist between iterations to track progress toward determining the next value.
My first attempt at making this loop more "functional" involved a tail-recursive function whose arguments included the array, the result set so far, the ranked list of values recently seen, and a few other items that need to persist between executions. This seems clunky, and I don't feel like I've gained anything by turning everything that used to be a variable into a parameter on this recursive function.
How would a functional programming master approach this kind of task? Is this an exceptional situation in which a "pure" functional approach doesn't quite fit, and am I wrong for eschewing mutable variables just because I feel they reduce the "purity" of my function? Maybe they don't make it less pure since they only exist inside that function's scope. I don't have a feel for that yet.
Here's an attempted distillation of the code, with some "let" statements and the actual components of state removed ("temp" is the intermediate result array that needs to be processed):
let fif (_,_,_,_,fif) = fif
temp
|> Array.fold (fun (a, b, c, tentativeNextVals, acc) curVal ->
if (hasProperty curVal c) then
// do not consider current value
(a, b, c, Seq.empty, acc)
else
if (hasOtherProperty curVal b) then
// add current value to tentative list
(a, b, c, tentativeNextVals.Concat [curVal], acc)
else
// accept a new value
let newAcceptedVal = chooseNextVal (tentativeNextVals.Concat [curVal])
(newC, newB, newC, Seq.empty, acc.Concat [newAcceptedVal])
) (0,0,0,Seq.empty,Seq.empty)
|> fif
Something like this using fold?
let filter list =
List.fold (fun statevar element -> if condition statevar then statevar else element) initialvalue list
Try using Seq.skip and Seq.take:
let subset (min, max) seq =
seq
|> Seq.skip (min)
|> Seq.take (max - min)
This function will accept arrays but return a sequence, so you can convert it back using Array.ofSeq.
PS: If your goal is to keep your program functional, the most important rule is this: avoid mutability as much as you can. This means that you probably shouldn't be using arrays; use lists which are immutable. If you're using an array for it's fast random access, go for it; just be sure to never set indices.

Can I use different workflows simultaneously in F#?

I need my state to be passed along while being able to chain functions with the maybe workflow. Is there a way for 2 workflows to share the same context? If no, what is the way of doing it?
UPDATE:
Well, I have a state that represents a segment of available ID's for the entities that I am going to create in the database. So once an ID is acquired the state has to be transformed to a newer state with the next available ID and thrown away so that nobody can use it again. I don't want to mutate the state for the sake of being idiomatic. The State monad looks like a way to go as it hides the transformation and passes the state along. Once the state workflow is in place I cannot use the Maybe workflow which is something I use everywhere.
As stated in the previous answer, one way to combine workflows in F# (Monads in Haskell) is by using a technique called Monad Transformers.
In F# this is really tricky, here is a project that deals with that technique.
It's possible to write the example of the previous answer by automatically combining State and Maybe (option), using that library:
#r #"c:\packages\FSharpPlus-1.0.0\lib\net45\FSharpPlus.dll"
open FSharpPlus
open FSharpPlus.Data
// Stateful computation
let computation =
monad {
let! x = get
let! y = OptionT (result (Some 10))
do! put (x + y)
let! x = get
return x
}
printfn "Result: %A" (State.eval (OptionT.run computation) 1)
So this is the other alternative, instead of creating your custom workflow, use a generic workflow that will be automatically inferred (a-la Haskell).
In F# you cannot easily mix different types of computation expressions as you would do in Haskell by using Monad Transformers or similar techniques. You could however build your own Monad, embedding state threading and optional values, as in:
type StateMaybe<'T> =
MyState -> option<'T> * MyState
// Runs the computation given an initial value and ignores the state result.
let evalState (sm: StateMaybe<'T>) = sm >> fst
// Computation expression for SateMaybe monad.
type StateMaybeBuilder() =
member this.Return<'T> (x: 'T) : StateMaybe<'T> = fun s -> (Some x, s)
member this.Bind(sm: StateMaybe<'T>, f: 'T -> StateMaybe<'S>) = fun s ->
let mx,s' = sm s
match mx with
| Some x -> f x s'
| None -> (None, s)
// Computation expression builder.
let maybeState = new StateMaybeBuilder()
// Lifts an optional value to a StateMaybe.
let liftOption<'T> (x: Option<'T>) : StateMaybe<'T> = fun s -> (x,s)
// Gets the current state.
let get : StateMaybe<MyState> = fun s -> (Some s,s)
// Puts a new state.
let put (x: MyState) : StateMaybe<unit> = fun _ -> (Some (), x)
Here's an example computation:
// Stateful computation
let computation =
maybeState {
let! x = get
let! y = liftOption (Some 10)
do! put (x + y)
let! x = get
return x
}
printfn "Result: %A" (evalState computation 1)
StateMaybe may be generalized further by making the type of the state component generic.
Others already gave you a direct answer to your question. However, I think that the way the question is stated leads to a solution that is not very idiomatic from the F# perspective - this might work for you as long as you are the only person working on the code, but I would recommend against doing that.
Even with the added details, the question is still fairly general, but here are two suggestions:
There is nothing wrong with reasonably used mutable state in F#. For example, it is perfectly fine to create a function that generates IDs and pass it along:
let createGenerator() =
let currentID = ref 0
(fun () -> incr currentID; !currentID)
Do you really need to generate the IDs while you are building the entities? It sounds like you could just generate a list of entities without ID and then use Seq.zip to zip the final list of entities with list of IDs.
As for the maybe computation, are you using it to handle regular, valid states, or to handle exceptional states? (It sounds like the first, which is the right way of doing things - but if you need to handle truly exceptional states, then you might want to use ordinary .NET exceptions).

What is "monadic reflection"?

What is "monadic reflection"?
How can I use it in F#-program?
Is the meaning of term "reflection" there same as .NET-reflection?
Monadic reflection is essentially a grammar for describing layered monads or monad layering. In Haskell describing also means constructing monads. This is a higher level system so the code looks like functional but the result is monad composition - meaning that without actual monads (which are non-functional) there's nothing real / runnable at the end of the day. Filinski did it originally to try to bring a kind of monad emulation to Scheme but much more to explore theoretical aspects of monads.
Correction from the comment - F# has a Monad equivalent named "Computation Expressions"
Filinski's paper at POPL 2010 - no code but a lot of theory, and of course his original paper from 1994 - Representing Monads. Plus one that has some code: Monad Transformers and Modular Interpreters (1995)
Oh and for people who like code - Filinski's code is on-line. I'll list just one - go one step up and see another 7 and readme. Also just a bit of F# code which claims to be inspired by Filinski
I read through the first Google hit, some slides:
http://www.cs.ioc.ee/mpc-amast06/msfp/filinski-slides.pdf
From this, it looks like
This is not the same as .NET reflection. The name seems to refer to turning data into code (and vice-versa, with reification).
The code uses standard pure-functional operations, so implementation should be easy in F#. (once you understand it)
I have no idea if this would be useful for implementing an immutable cache for a recursive function. It look like you can define mutable operations and convert them to equivalent immutable operations automatically? I don't really understand the slides.
Oleg Kiselyov also has an article, but I didn't even try to read it. There's also a paper from Jonathan Sobel (et al). Hit number 5 is this question, so I stopped looking after that.
As previous answers links describes, Monadic reflection is a concept to bridge call/cc style and Church style programming. To describe these two concepts some more:
F# Computation expressions (=monads) are created with custom Builder type.
Don Syme has a good blog post about this. If I write code to use a builder and use syntax like:
attempt { let! n1 = f inp1
let! n2 = failIfBig inp2
let sum = n1 + n2
return sum }
the syntax is translated to call/cc "call-with-current-continuation" style program:
attempt.Delay(fun () ->
attempt.Bind(f inp1,(fun n1 ->
attempt.Bind(f inp2,(fun n2 ->
attempt.Let(n1 + n2,(fun sum ->
attempt.Return(sum))))))))
The last parameter is the next-command-to-be-executed until the end.
(Scheme-style programming.)
F# is based on OCaml.
F# has partial function application, but it also is strongly typed and has value restriction.
But OCaml don't have value restriction.
OCaml can be used in Church kind of programming, where combinator-functions are used to construct any other functions (or programs):
// S K I combinators:
let I x = x
let K x y = x
let S x y z = x z (y z)
//examples:
let seven = S (K) (K) 7
let doubleI = I I //Won't work in F#
// y-combinator to make recursion
let Y = S (K (S I I)) (S (S (K S) K) (K (S I I)))
Church numerals is a way to represent numbers with pure functions.
let zero f x = x
//same as: let zero = fun f -> fun x -> x
let succ n f x = f (n f x)
let one = succ zero
let two = succ (succ zero)
let add n1 n2 f x = n1 f (n2 f x)
let multiply n1 n2 f = n2(n1(f))
let exp n1 n2 = n2(n1)
Here, zero is a function that takes two functions as parameters: f is applied zero times so this represent the number zero, and x is used to function combination in other calculations (like add). succ function is like plusOne so one = zero |> plusOne.
To execute the functions, the last function will call the other functions with last parameter (x) as null.
(Haskell-style programming.)
In F# value restriction makes this hard. Church numerals can be made with C# 4.0 dynamic keyword (which uses .NET reflection inside). I think there are workarounds to do that also in F#.

Ranges A to B where A > B in F#

I've just found something I'd call a quirk in F# and would like to know whether it's by design or by mistake and if it's by design, why is it so...
If you write any range expression where the first term is greater than the second term the returned sequence is empty. A look at reflector suggests this is by design, but I can't really find a reason why it would have to be so.
An example to reproduce it is:
[1..10] |> List.length
[10..1] |> List.length
The first will print out 10 while the second will print out 0.
Tests were made in F# CTP 1.9.6.2.
EDIT: thanks for suggesting expliciting the range, but there's still one case (which is what inspired me to ask this question) that won't be covered. What if A and B are variables and none is constantly greater than the other although they're always different?
Considering that the range expression does not seem to get optimized at compiled time anyway, is there any good reason for the code which determines the step (not explicitly specified) in case A and B are ints not to allow negative steps?
As suggested by other answers, you can do
[10 .. -1 .. 1] |> List.iter (printfn "%A")
e.g.
[start .. step .. stop]
Adam Wright - But you should be able
to change the binding for types you're
interested in to behave in any way you
like (including counting down if x >
y).
Taking Adam's suggestion into code:
let (..) a b =
if a < b then seq { a .. b }
else seq { a .. -1 .. b }
printfn "%A" (seq { 1 .. 10 })
printfn "%A" (seq { 10 .. 1 })
This works for int ranges. Have a look at the source code for (..): you may be able to use that to work over other types of ranges, but not sure how you would get the right value of -1 for your specific type.
What "should" happen is, of course, subjective. Normal range notation in my mind defines [x..y] as the set of all elements greater than or equal to x AND less than or equal to y; an empty set if y < x. In this case, we need to appeal to the F# spec.
Range expressions expr1 .. expr2 are evaluated as a call to the overloaded operator (..), whose default binding is defined in Microsoft.FSharp.Core.Operators. This generates an IEnumerable<_> for the range of values between the given start (expr1) and finish (expr2) values, using an increment of 1. The operator requires the existence of a static member (..) (long name GetRange) on the static type of expr1 with an appropriate signature.
Range expressions expr1 .. expr2 .. expr3 are evaluated as a call to the overloaded operator (.. ..), whose default binding is defined in Microsoft.FSharp.Core.Operators. This generates an IEnumerable<_> for the range of values between the given start (expr1) and finish (expr3) values, using an increment of expr2. The operator requires the existence of a static member (..) (long name GetRange) on the static type of expr1 with an appropriate signature.
The standard doesn't seem to define the .. operator (a least, that I can find). But you should be able to change the binding for types you're interested in to behave in any way you like (including counting down if x > y).
In haskell, you can write [10, 9 .. 1]. Perhaps it works the same in F# (I haven't tried it)?
edit:
It seems that the F# syntax is different, maybe something like [10..-1..1]
Ranges are generally expressed (in the languages and frameworks that support them) like this:
low_value <to> high_value
Can you give a good argument why a range ought to be able to be expressed differently? Since you were requesting a range from a higher number to a lower number does it not stand to reason that the resulting range would have no members?

Resources