C# Continuation Monad ImplementationDoes an IO monad make sense in a language like C#How do I calculate someone's age in C#?What is the difference between String and string in C#?Hidden Features of C#?Cast int to enum in C#What is a monad?How do I enumerate an enum in C#?What are the correct version numbers for C#?Monad in plain English? (For the OOP programmer with no FP background)A monad is just a monoid in the category of endofunctors, what's the problem?Why do we need monads?
How can a single Member of the House block a Congressional bill?
Applicants clearly not having the skills they advertise
Is it possible to kill all life on Earth?
Access to all elements on the page
Show sparse matrices like chessboards
Can a class take a different class's spell in their ritual book?
GFCI Outlet in Bathroom, Lights not working
How can Iron Man's suit withstand this?
Do adult Russians normally hand-write Cyrillic as cursive or as block letters?
Can an old DSLR be upgraded to match modern smartphone image quality
What does War Machine's "Canopy! Canopy!" line mean in "Avengers: Endgame"?
Hygienic footwear for prehensile feet?
Strange math syntax in old basic listing
How to provide realism without making readers think grimdark
How to apply the "glow" effect to a rectangle with tcolorbox?
Credit card offering 0.5 miles for every cent rounded up. Too good to be true?
How can I offer a test ride while selling a bike?
Is there a rule that prohibits us from using 2 possessives in a row?
Pros and cons of writing a book review?
Word for a small burst of laughter that can't be held back
What is the best option to connect old computer to modern TV
Will dual-learning in a glider make my airplane learning safer?
How to decline physical affection from a child whose parents are pressuring them?
Rotated Position of Integers
C# Continuation Monad Implementation
Does an IO monad make sense in a language like C#How do I calculate someone's age in C#?What is the difference between String and string in C#?Hidden Features of C#?Cast int to enum in C#What is a monad?How do I enumerate an enum in C#?What are the correct version numbers for C#?Monad in plain English? (For the OOP programmer with no FP background)A monad is just a monoid in the category of endofunctors, what's the problem?Why do we need monads?
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;
I have been working on allowing function chaining. I have created a class called continuationmonad which takes a value, and a function from a => b. This allows me to use fmap and bind to chain these together. I have also used lazy to allowed calls to be defered where possible.
Is this class really the continuation monad or is it something else. I am finding it hard to find good literature which is not is Haskell.
Also any comments on how to improve / correct this.
using NUnit.Framework;
using System;
namespace Monads
public class Continuation<Input, Output>
public Continuation(Input value, Func<Input,Output> function)
this.value = new Lazy<Input>( () => value);
this.function = function;
public Continuation(Lazy<Input> value, Func<Input,Output> function)
this.value = value;
this.function = function;
public Continuation<Output, Result> FMap<Result>(Func<Output, Result> map)
return new Continuation<Output, Result>(new Lazy<Output>( () => Run() ), x => map(x));
public Continuation<Output,Result> Bind<Result>(Func<Output, Continuation<Output, Result>> f)
return f(Run());
public Output Run()
return function(value.Value);
private Func<Input, Output> function;
private Lazy<Input> value;
public static class ContinuationExtension
public static Continuation<A,B> Unit<A,B>(this Func<A,B> f, A value)
return new Continuation<A, B>(value,f);
public static Continuation<A,B> Unit<A,B>(this A value,Func<A,B> f)
return new Continuation<A, B>(value,f);
[TestFixture]
public class MonadTests
public Continuation<int,int> Wrapped(int value)
return new Continuation<int,int>(value, x => x * 10);
[Test]
public void ContinuationMonadTests()
var number = 42;
var result = number.Unit(x => x + 8).FMap(x => x * 2).Bind(Wrapped).Run();
Console.WriteLine(result);
c# haskell functional-programming monads
add a comment |
I have been working on allowing function chaining. I have created a class called continuationmonad which takes a value, and a function from a => b. This allows me to use fmap and bind to chain these together. I have also used lazy to allowed calls to be defered where possible.
Is this class really the continuation monad or is it something else. I am finding it hard to find good literature which is not is Haskell.
Also any comments on how to improve / correct this.
using NUnit.Framework;
using System;
namespace Monads
public class Continuation<Input, Output>
public Continuation(Input value, Func<Input,Output> function)
this.value = new Lazy<Input>( () => value);
this.function = function;
public Continuation(Lazy<Input> value, Func<Input,Output> function)
this.value = value;
this.function = function;
public Continuation<Output, Result> FMap<Result>(Func<Output, Result> map)
return new Continuation<Output, Result>(new Lazy<Output>( () => Run() ), x => map(x));
public Continuation<Output,Result> Bind<Result>(Func<Output, Continuation<Output, Result>> f)
return f(Run());
public Output Run()
return function(value.Value);
private Func<Input, Output> function;
private Lazy<Input> value;
public static class ContinuationExtension
public static Continuation<A,B> Unit<A,B>(this Func<A,B> f, A value)
return new Continuation<A, B>(value,f);
public static Continuation<A,B> Unit<A,B>(this A value,Func<A,B> f)
return new Continuation<A, B>(value,f);
[TestFixture]
public class MonadTests
public Continuation<int,int> Wrapped(int value)
return new Continuation<int,int>(value, x => x * 10);
[Test]
public void ContinuationMonadTests()
var number = 42;
var result = number.Unit(x => x + 8).FMap(x => x * 2).Bind(Wrapped).Run();
Console.WriteLine(result);
c# haskell functional-programming monads
add a comment |
I have been working on allowing function chaining. I have created a class called continuationmonad which takes a value, and a function from a => b. This allows me to use fmap and bind to chain these together. I have also used lazy to allowed calls to be defered where possible.
Is this class really the continuation monad or is it something else. I am finding it hard to find good literature which is not is Haskell.
Also any comments on how to improve / correct this.
using NUnit.Framework;
using System;
namespace Monads
public class Continuation<Input, Output>
public Continuation(Input value, Func<Input,Output> function)
this.value = new Lazy<Input>( () => value);
this.function = function;
public Continuation(Lazy<Input> value, Func<Input,Output> function)
this.value = value;
this.function = function;
public Continuation<Output, Result> FMap<Result>(Func<Output, Result> map)
return new Continuation<Output, Result>(new Lazy<Output>( () => Run() ), x => map(x));
public Continuation<Output,Result> Bind<Result>(Func<Output, Continuation<Output, Result>> f)
return f(Run());
public Output Run()
return function(value.Value);
private Func<Input, Output> function;
private Lazy<Input> value;
public static class ContinuationExtension
public static Continuation<A,B> Unit<A,B>(this Func<A,B> f, A value)
return new Continuation<A, B>(value,f);
public static Continuation<A,B> Unit<A,B>(this A value,Func<A,B> f)
return new Continuation<A, B>(value,f);
[TestFixture]
public class MonadTests
public Continuation<int,int> Wrapped(int value)
return new Continuation<int,int>(value, x => x * 10);
[Test]
public void ContinuationMonadTests()
var number = 42;
var result = number.Unit(x => x + 8).FMap(x => x * 2).Bind(Wrapped).Run();
Console.WriteLine(result);
c# haskell functional-programming monads
I have been working on allowing function chaining. I have created a class called continuationmonad which takes a value, and a function from a => b. This allows me to use fmap and bind to chain these together. I have also used lazy to allowed calls to be defered where possible.
Is this class really the continuation monad or is it something else. I am finding it hard to find good literature which is not is Haskell.
Also any comments on how to improve / correct this.
using NUnit.Framework;
using System;
namespace Monads
public class Continuation<Input, Output>
public Continuation(Input value, Func<Input,Output> function)
this.value = new Lazy<Input>( () => value);
this.function = function;
public Continuation(Lazy<Input> value, Func<Input,Output> function)
this.value = value;
this.function = function;
public Continuation<Output, Result> FMap<Result>(Func<Output, Result> map)
return new Continuation<Output, Result>(new Lazy<Output>( () => Run() ), x => map(x));
public Continuation<Output,Result> Bind<Result>(Func<Output, Continuation<Output, Result>> f)
return f(Run());
public Output Run()
return function(value.Value);
private Func<Input, Output> function;
private Lazy<Input> value;
public static class ContinuationExtension
public static Continuation<A,B> Unit<A,B>(this Func<A,B> f, A value)
return new Continuation<A, B>(value,f);
public static Continuation<A,B> Unit<A,B>(this A value,Func<A,B> f)
return new Continuation<A, B>(value,f);
[TestFixture]
public class MonadTests
public Continuation<int,int> Wrapped(int value)
return new Continuation<int,int>(value, x => x * 10);
[Test]
public void ContinuationMonadTests()
var number = 42;
var result = number.Unit(x => x + 8).FMap(x => x * 2).Bind(Wrapped).Run();
Console.WriteLine(result);
c# haskell functional-programming monads
c# haskell functional-programming monads
asked Oct 13 '14 at 3:24
Blair DavidsonBlair Davidson
494628
494628
add a comment |
add a comment |
3 Answers
3
active
oldest
votes
This is not the continuation monad. You are much closer to the Haskell Monad
instance for functions.
You aren't getting anything that you couldn't get just from using Lazy<>
. Since you have provided the input when you build an instance of your class, you aren't building functions, you are building values that are determined by a computation that hasn't been evaluated yet. Lazy<>
delays the evaluation of computation until the value is needed.
Let's put together something like the Haskell Monad
instance for functions in c#. LINQ syntax has established the convention for Monad
s in c#. They should have:
- a
Select
extension method analogous to a HaskellFunctor
'sfmap
- a
SelectMany
extension method analogous to Haskell'sMonad
's>>=
- an additional
SelectMany
that LINQ syntax uses. This takes an additional function that combines the value from two steps together.
Unfortunately, there's no convention for what the analog of a Monad
's return
should be called; we'll call ours Constant
. Unfortunately, Constant
won't be very convenient because c#'s type inference won't be able to figure out the types.
public static class Function
public static Func<TIn, TOut> Constant<TIn, TOut>(TOut result)
return x => result;
public static Func<TIn, TOut> Select<TIn, TMid, TOut>(
this Func<TIn, TMid> func,
Func<TMid, TOut> proj)
return x => proj(func(x));
public static Func<TIn, TOut> SelectMany<TIn, TMid, TOut>(
this Func<TIn, TMid> func,
Func<TMid, Func<TIn, TOut>> proj)
return x => proj(func(x))(x);
public static Func<TIn, TOut> SelectMany<TIn, TMid1, TMid2, TOut>(
this Func<TIn, TMid1> func,
Func<TMid1, Func<TIn, TMid2>> proj1,
Func<TMid1, TMid2, TOut> proj2)
return x =>
var mid1 = func(x);
var mid2 = proj1(mid1)(x);
return proj2(mid1, mid2);
;
Note that defining these extension methods only lets you interact with something like it's a Monad
, it doesn't let you write code that's generic over the specific Monad
being used. There's a sketch of how to do that in the second half of this answer.
Your answer did pop up in the same instant I just hit the button :D - +1 for the surely better answer
– Carsten
Oct 13 '14 at 4:24
1
why can'tFunc<,>
be the first value of an extension method? Seems to work fine on first glance: gist.github.com/CarstenKoenig/26e46150c6458609d756
– Carsten
Oct 13 '14 at 4:51
add a comment |
This might be a bit opinion based but I'll try to give you my 5ct anyway.
Let's have a look at your class and their instances:
It includes a value and a function where you (tried) to make it all a lazy.
From a theoretical view I can see no difference to Lazy<T>
on first glance:
You can surely convert one of your Continuation<Input,Output>
to just a Lazy<Output>
.
The same is true for the reverse: given some lazy value a
you can make a instance with just
new Continuation(a, x => x)
So to me it seems that you just reinvented Lazy
(which is an monad, in Haskell you would call it Identity
.
The Cont
monad is not really easy to crasp but it's really more related to .net-Events or .net-Observables. The datastructure itself would be like
Func<Func<Input,Output>, Output>
Where you pass in a continuation Func<Input,Output>
to some internal calculation and then the struture than will call it when it has calculated an input Input
to get the final result.
This might be a bit cryptic but one .net application are the Async
workflows F# uses and which stood model for C#s async/await behaviour in some sense.
I have some material I used for a talk on a simpified version of this monad in C# on github maybe you'll find it interesting.
+1 for recognizing thatLazy<>
is Haskell'sIdentity
. In c# an idiomaticIdentity
would probably be strict.
– Cirdec
Oct 13 '14 at 4:23
add a comment |
I have created a very comprehensive introduction to the Continuation monad that you can Find Here Discovering the Continuation Monad in C#
Also you can find a.Net Fiddle here
I Repeat it in summary here
Starting from an initial Function
int Square(int x )return (x * x);
- Use Callback and remove return type
public static void Square(int x, Action<int> callback)
callback(x * x);
- Curry the Callback
public static Action<Action<int>> Square(int x)
return (callback) => callback(x * x); ;
- Generalize the returned Continuation
public static Func<Func<int,T>,T> Square<T>(int x)
return (callback) => callback(x * x); ;
- Extract the Continuation Structure Also Known As the Return Method of the monad. That is Give me a value and i will give you a Monad for this value
//((U→ T) → T)
delegate T Cont<U, T>(Func<U, T> f);
public static Cont<U, T> ToContinuation<U, T>(this U x)
return (callback) => callback(x);
square.ToContinuation<Func<int, int>, int>()
- Add The bind Monadic method and thus Complete the Monad.That is Give me a Two Monads and i will combine them to a new monad
((A→ T) → T)→( A→((B→ T) → T))→ ((B→ T) → T)
public static Cont<V, Answer> Bind<T, U, V, Answer>(
this Cont<T, Answer> m,
Func<T, Cont<U, Answer>> k,
Func<T, U, V> selector)
return (Func<V, Answer> c) =>
m(t => k(t)(y => c(selector(t, y))));
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f26332494%2fc-sharp-continuation-monad-implementation%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
This is not the continuation monad. You are much closer to the Haskell Monad
instance for functions.
You aren't getting anything that you couldn't get just from using Lazy<>
. Since you have provided the input when you build an instance of your class, you aren't building functions, you are building values that are determined by a computation that hasn't been evaluated yet. Lazy<>
delays the evaluation of computation until the value is needed.
Let's put together something like the Haskell Monad
instance for functions in c#. LINQ syntax has established the convention for Monad
s in c#. They should have:
- a
Select
extension method analogous to a HaskellFunctor
'sfmap
- a
SelectMany
extension method analogous to Haskell'sMonad
's>>=
- an additional
SelectMany
that LINQ syntax uses. This takes an additional function that combines the value from two steps together.
Unfortunately, there's no convention for what the analog of a Monad
's return
should be called; we'll call ours Constant
. Unfortunately, Constant
won't be very convenient because c#'s type inference won't be able to figure out the types.
public static class Function
public static Func<TIn, TOut> Constant<TIn, TOut>(TOut result)
return x => result;
public static Func<TIn, TOut> Select<TIn, TMid, TOut>(
this Func<TIn, TMid> func,
Func<TMid, TOut> proj)
return x => proj(func(x));
public static Func<TIn, TOut> SelectMany<TIn, TMid, TOut>(
this Func<TIn, TMid> func,
Func<TMid, Func<TIn, TOut>> proj)
return x => proj(func(x))(x);
public static Func<TIn, TOut> SelectMany<TIn, TMid1, TMid2, TOut>(
this Func<TIn, TMid1> func,
Func<TMid1, Func<TIn, TMid2>> proj1,
Func<TMid1, TMid2, TOut> proj2)
return x =>
var mid1 = func(x);
var mid2 = proj1(mid1)(x);
return proj2(mid1, mid2);
;
Note that defining these extension methods only lets you interact with something like it's a Monad
, it doesn't let you write code that's generic over the specific Monad
being used. There's a sketch of how to do that in the second half of this answer.
Your answer did pop up in the same instant I just hit the button :D - +1 for the surely better answer
– Carsten
Oct 13 '14 at 4:24
1
why can'tFunc<,>
be the first value of an extension method? Seems to work fine on first glance: gist.github.com/CarstenKoenig/26e46150c6458609d756
– Carsten
Oct 13 '14 at 4:51
add a comment |
This is not the continuation monad. You are much closer to the Haskell Monad
instance for functions.
You aren't getting anything that you couldn't get just from using Lazy<>
. Since you have provided the input when you build an instance of your class, you aren't building functions, you are building values that are determined by a computation that hasn't been evaluated yet. Lazy<>
delays the evaluation of computation until the value is needed.
Let's put together something like the Haskell Monad
instance for functions in c#. LINQ syntax has established the convention for Monad
s in c#. They should have:
- a
Select
extension method analogous to a HaskellFunctor
'sfmap
- a
SelectMany
extension method analogous to Haskell'sMonad
's>>=
- an additional
SelectMany
that LINQ syntax uses. This takes an additional function that combines the value from two steps together.
Unfortunately, there's no convention for what the analog of a Monad
's return
should be called; we'll call ours Constant
. Unfortunately, Constant
won't be very convenient because c#'s type inference won't be able to figure out the types.
public static class Function
public static Func<TIn, TOut> Constant<TIn, TOut>(TOut result)
return x => result;
public static Func<TIn, TOut> Select<TIn, TMid, TOut>(
this Func<TIn, TMid> func,
Func<TMid, TOut> proj)
return x => proj(func(x));
public static Func<TIn, TOut> SelectMany<TIn, TMid, TOut>(
this Func<TIn, TMid> func,
Func<TMid, Func<TIn, TOut>> proj)
return x => proj(func(x))(x);
public static Func<TIn, TOut> SelectMany<TIn, TMid1, TMid2, TOut>(
this Func<TIn, TMid1> func,
Func<TMid1, Func<TIn, TMid2>> proj1,
Func<TMid1, TMid2, TOut> proj2)
return x =>
var mid1 = func(x);
var mid2 = proj1(mid1)(x);
return proj2(mid1, mid2);
;
Note that defining these extension methods only lets you interact with something like it's a Monad
, it doesn't let you write code that's generic over the specific Monad
being used. There's a sketch of how to do that in the second half of this answer.
Your answer did pop up in the same instant I just hit the button :D - +1 for the surely better answer
– Carsten
Oct 13 '14 at 4:24
1
why can'tFunc<,>
be the first value of an extension method? Seems to work fine on first glance: gist.github.com/CarstenKoenig/26e46150c6458609d756
– Carsten
Oct 13 '14 at 4:51
add a comment |
This is not the continuation monad. You are much closer to the Haskell Monad
instance for functions.
You aren't getting anything that you couldn't get just from using Lazy<>
. Since you have provided the input when you build an instance of your class, you aren't building functions, you are building values that are determined by a computation that hasn't been evaluated yet. Lazy<>
delays the evaluation of computation until the value is needed.
Let's put together something like the Haskell Monad
instance for functions in c#. LINQ syntax has established the convention for Monad
s in c#. They should have:
- a
Select
extension method analogous to a HaskellFunctor
'sfmap
- a
SelectMany
extension method analogous to Haskell'sMonad
's>>=
- an additional
SelectMany
that LINQ syntax uses. This takes an additional function that combines the value from two steps together.
Unfortunately, there's no convention for what the analog of a Monad
's return
should be called; we'll call ours Constant
. Unfortunately, Constant
won't be very convenient because c#'s type inference won't be able to figure out the types.
public static class Function
public static Func<TIn, TOut> Constant<TIn, TOut>(TOut result)
return x => result;
public static Func<TIn, TOut> Select<TIn, TMid, TOut>(
this Func<TIn, TMid> func,
Func<TMid, TOut> proj)
return x => proj(func(x));
public static Func<TIn, TOut> SelectMany<TIn, TMid, TOut>(
this Func<TIn, TMid> func,
Func<TMid, Func<TIn, TOut>> proj)
return x => proj(func(x))(x);
public static Func<TIn, TOut> SelectMany<TIn, TMid1, TMid2, TOut>(
this Func<TIn, TMid1> func,
Func<TMid1, Func<TIn, TMid2>> proj1,
Func<TMid1, TMid2, TOut> proj2)
return x =>
var mid1 = func(x);
var mid2 = proj1(mid1)(x);
return proj2(mid1, mid2);
;
Note that defining these extension methods only lets you interact with something like it's a Monad
, it doesn't let you write code that's generic over the specific Monad
being used. There's a sketch of how to do that in the second half of this answer.
This is not the continuation monad. You are much closer to the Haskell Monad
instance for functions.
You aren't getting anything that you couldn't get just from using Lazy<>
. Since you have provided the input when you build an instance of your class, you aren't building functions, you are building values that are determined by a computation that hasn't been evaluated yet. Lazy<>
delays the evaluation of computation until the value is needed.
Let's put together something like the Haskell Monad
instance for functions in c#. LINQ syntax has established the convention for Monad
s in c#. They should have:
- a
Select
extension method analogous to a HaskellFunctor
'sfmap
- a
SelectMany
extension method analogous to Haskell'sMonad
's>>=
- an additional
SelectMany
that LINQ syntax uses. This takes an additional function that combines the value from two steps together.
Unfortunately, there's no convention for what the analog of a Monad
's return
should be called; we'll call ours Constant
. Unfortunately, Constant
won't be very convenient because c#'s type inference won't be able to figure out the types.
public static class Function
public static Func<TIn, TOut> Constant<TIn, TOut>(TOut result)
return x => result;
public static Func<TIn, TOut> Select<TIn, TMid, TOut>(
this Func<TIn, TMid> func,
Func<TMid, TOut> proj)
return x => proj(func(x));
public static Func<TIn, TOut> SelectMany<TIn, TMid, TOut>(
this Func<TIn, TMid> func,
Func<TMid, Func<TIn, TOut>> proj)
return x => proj(func(x))(x);
public static Func<TIn, TOut> SelectMany<TIn, TMid1, TMid2, TOut>(
this Func<TIn, TMid1> func,
Func<TMid1, Func<TIn, TMid2>> proj1,
Func<TMid1, TMid2, TOut> proj2)
return x =>
var mid1 = func(x);
var mid2 = proj1(mid1)(x);
return proj2(mid1, mid2);
;
Note that defining these extension methods only lets you interact with something like it's a Monad
, it doesn't let you write code that's generic over the specific Monad
being used. There's a sketch of how to do that in the second half of this answer.
edited May 23 '17 at 11:52
Community♦
11
11
answered Oct 13 '14 at 4:20
CirdecCirdec
22k23985
22k23985
Your answer did pop up in the same instant I just hit the button :D - +1 for the surely better answer
– Carsten
Oct 13 '14 at 4:24
1
why can'tFunc<,>
be the first value of an extension method? Seems to work fine on first glance: gist.github.com/CarstenKoenig/26e46150c6458609d756
– Carsten
Oct 13 '14 at 4:51
add a comment |
Your answer did pop up in the same instant I just hit the button :D - +1 for the surely better answer
– Carsten
Oct 13 '14 at 4:24
1
why can'tFunc<,>
be the first value of an extension method? Seems to work fine on first glance: gist.github.com/CarstenKoenig/26e46150c6458609d756
– Carsten
Oct 13 '14 at 4:51
Your answer did pop up in the same instant I just hit the button :D - +1 for the surely better answer
– Carsten
Oct 13 '14 at 4:24
Your answer did pop up in the same instant I just hit the button :D - +1 for the surely better answer
– Carsten
Oct 13 '14 at 4:24
1
1
why can't
Func<,>
be the first value of an extension method? Seems to work fine on first glance: gist.github.com/CarstenKoenig/26e46150c6458609d756– Carsten
Oct 13 '14 at 4:51
why can't
Func<,>
be the first value of an extension method? Seems to work fine on first glance: gist.github.com/CarstenKoenig/26e46150c6458609d756– Carsten
Oct 13 '14 at 4:51
add a comment |
This might be a bit opinion based but I'll try to give you my 5ct anyway.
Let's have a look at your class and their instances:
It includes a value and a function where you (tried) to make it all a lazy.
From a theoretical view I can see no difference to Lazy<T>
on first glance:
You can surely convert one of your Continuation<Input,Output>
to just a Lazy<Output>
.
The same is true for the reverse: given some lazy value a
you can make a instance with just
new Continuation(a, x => x)
So to me it seems that you just reinvented Lazy
(which is an monad, in Haskell you would call it Identity
.
The Cont
monad is not really easy to crasp but it's really more related to .net-Events or .net-Observables. The datastructure itself would be like
Func<Func<Input,Output>, Output>
Where you pass in a continuation Func<Input,Output>
to some internal calculation and then the struture than will call it when it has calculated an input Input
to get the final result.
This might be a bit cryptic but one .net application are the Async
workflows F# uses and which stood model for C#s async/await behaviour in some sense.
I have some material I used for a talk on a simpified version of this monad in C# on github maybe you'll find it interesting.
+1 for recognizing thatLazy<>
is Haskell'sIdentity
. In c# an idiomaticIdentity
would probably be strict.
– Cirdec
Oct 13 '14 at 4:23
add a comment |
This might be a bit opinion based but I'll try to give you my 5ct anyway.
Let's have a look at your class and their instances:
It includes a value and a function where you (tried) to make it all a lazy.
From a theoretical view I can see no difference to Lazy<T>
on first glance:
You can surely convert one of your Continuation<Input,Output>
to just a Lazy<Output>
.
The same is true for the reverse: given some lazy value a
you can make a instance with just
new Continuation(a, x => x)
So to me it seems that you just reinvented Lazy
(which is an monad, in Haskell you would call it Identity
.
The Cont
monad is not really easy to crasp but it's really more related to .net-Events or .net-Observables. The datastructure itself would be like
Func<Func<Input,Output>, Output>
Where you pass in a continuation Func<Input,Output>
to some internal calculation and then the struture than will call it when it has calculated an input Input
to get the final result.
This might be a bit cryptic but one .net application are the Async
workflows F# uses and which stood model for C#s async/await behaviour in some sense.
I have some material I used for a talk on a simpified version of this monad in C# on github maybe you'll find it interesting.
+1 for recognizing thatLazy<>
is Haskell'sIdentity
. In c# an idiomaticIdentity
would probably be strict.
– Cirdec
Oct 13 '14 at 4:23
add a comment |
This might be a bit opinion based but I'll try to give you my 5ct anyway.
Let's have a look at your class and their instances:
It includes a value and a function where you (tried) to make it all a lazy.
From a theoretical view I can see no difference to Lazy<T>
on first glance:
You can surely convert one of your Continuation<Input,Output>
to just a Lazy<Output>
.
The same is true for the reverse: given some lazy value a
you can make a instance with just
new Continuation(a, x => x)
So to me it seems that you just reinvented Lazy
(which is an monad, in Haskell you would call it Identity
.
The Cont
monad is not really easy to crasp but it's really more related to .net-Events or .net-Observables. The datastructure itself would be like
Func<Func<Input,Output>, Output>
Where you pass in a continuation Func<Input,Output>
to some internal calculation and then the struture than will call it when it has calculated an input Input
to get the final result.
This might be a bit cryptic but one .net application are the Async
workflows F# uses and which stood model for C#s async/await behaviour in some sense.
I have some material I used for a talk on a simpified version of this monad in C# on github maybe you'll find it interesting.
This might be a bit opinion based but I'll try to give you my 5ct anyway.
Let's have a look at your class and their instances:
It includes a value and a function where you (tried) to make it all a lazy.
From a theoretical view I can see no difference to Lazy<T>
on first glance:
You can surely convert one of your Continuation<Input,Output>
to just a Lazy<Output>
.
The same is true for the reverse: given some lazy value a
you can make a instance with just
new Continuation(a, x => x)
So to me it seems that you just reinvented Lazy
(which is an monad, in Haskell you would call it Identity
.
The Cont
monad is not really easy to crasp but it's really more related to .net-Events or .net-Observables. The datastructure itself would be like
Func<Func<Input,Output>, Output>
Where you pass in a continuation Func<Input,Output>
to some internal calculation and then the struture than will call it when it has calculated an input Input
to get the final result.
This might be a bit cryptic but one .net application are the Async
workflows F# uses and which stood model for C#s async/await behaviour in some sense.
I have some material I used for a talk on a simpified version of this monad in C# on github maybe you'll find it interesting.
answered Oct 13 '14 at 4:20
CarstenCarsten
44.6k672105
44.6k672105
+1 for recognizing thatLazy<>
is Haskell'sIdentity
. In c# an idiomaticIdentity
would probably be strict.
– Cirdec
Oct 13 '14 at 4:23
add a comment |
+1 for recognizing thatLazy<>
is Haskell'sIdentity
. In c# an idiomaticIdentity
would probably be strict.
– Cirdec
Oct 13 '14 at 4:23
+1 for recognizing that
Lazy<>
is Haskell's Identity
. In c# an idiomatic Identity
would probably be strict.– Cirdec
Oct 13 '14 at 4:23
+1 for recognizing that
Lazy<>
is Haskell's Identity
. In c# an idiomatic Identity
would probably be strict.– Cirdec
Oct 13 '14 at 4:23
add a comment |
I have created a very comprehensive introduction to the Continuation monad that you can Find Here Discovering the Continuation Monad in C#
Also you can find a.Net Fiddle here
I Repeat it in summary here
Starting from an initial Function
int Square(int x )return (x * x);
- Use Callback and remove return type
public static void Square(int x, Action<int> callback)
callback(x * x);
- Curry the Callback
public static Action<Action<int>> Square(int x)
return (callback) => callback(x * x); ;
- Generalize the returned Continuation
public static Func<Func<int,T>,T> Square<T>(int x)
return (callback) => callback(x * x); ;
- Extract the Continuation Structure Also Known As the Return Method of the monad. That is Give me a value and i will give you a Monad for this value
//((U→ T) → T)
delegate T Cont<U, T>(Func<U, T> f);
public static Cont<U, T> ToContinuation<U, T>(this U x)
return (callback) => callback(x);
square.ToContinuation<Func<int, int>, int>()
- Add The bind Monadic method and thus Complete the Monad.That is Give me a Two Monads and i will combine them to a new monad
((A→ T) → T)→( A→((B→ T) → T))→ ((B→ T) → T)
public static Cont<V, Answer> Bind<T, U, V, Answer>(
this Cont<T, Answer> m,
Func<T, Cont<U, Answer>> k,
Func<T, U, V> selector)
return (Func<V, Answer> c) =>
m(t => k(t)(y => c(selector(t, y))));
add a comment |
I have created a very comprehensive introduction to the Continuation monad that you can Find Here Discovering the Continuation Monad in C#
Also you can find a.Net Fiddle here
I Repeat it in summary here
Starting from an initial Function
int Square(int x )return (x * x);
- Use Callback and remove return type
public static void Square(int x, Action<int> callback)
callback(x * x);
- Curry the Callback
public static Action<Action<int>> Square(int x)
return (callback) => callback(x * x); ;
- Generalize the returned Continuation
public static Func<Func<int,T>,T> Square<T>(int x)
return (callback) => callback(x * x); ;
- Extract the Continuation Structure Also Known As the Return Method of the monad. That is Give me a value and i will give you a Monad for this value
//((U→ T) → T)
delegate T Cont<U, T>(Func<U, T> f);
public static Cont<U, T> ToContinuation<U, T>(this U x)
return (callback) => callback(x);
square.ToContinuation<Func<int, int>, int>()
- Add The bind Monadic method and thus Complete the Monad.That is Give me a Two Monads and i will combine them to a new monad
((A→ T) → T)→( A→((B→ T) → T))→ ((B→ T) → T)
public static Cont<V, Answer> Bind<T, U, V, Answer>(
this Cont<T, Answer> m,
Func<T, Cont<U, Answer>> k,
Func<T, U, V> selector)
return (Func<V, Answer> c) =>
m(t => k(t)(y => c(selector(t, y))));
add a comment |
I have created a very comprehensive introduction to the Continuation monad that you can Find Here Discovering the Continuation Monad in C#
Also you can find a.Net Fiddle here
I Repeat it in summary here
Starting from an initial Function
int Square(int x )return (x * x);
- Use Callback and remove return type
public static void Square(int x, Action<int> callback)
callback(x * x);
- Curry the Callback
public static Action<Action<int>> Square(int x)
return (callback) => callback(x * x); ;
- Generalize the returned Continuation
public static Func<Func<int,T>,T> Square<T>(int x)
return (callback) => callback(x * x); ;
- Extract the Continuation Structure Also Known As the Return Method of the monad. That is Give me a value and i will give you a Monad for this value
//((U→ T) → T)
delegate T Cont<U, T>(Func<U, T> f);
public static Cont<U, T> ToContinuation<U, T>(this U x)
return (callback) => callback(x);
square.ToContinuation<Func<int, int>, int>()
- Add The bind Monadic method and thus Complete the Monad.That is Give me a Two Monads and i will combine them to a new monad
((A→ T) → T)→( A→((B→ T) → T))→ ((B→ T) → T)
public static Cont<V, Answer> Bind<T, U, V, Answer>(
this Cont<T, Answer> m,
Func<T, Cont<U, Answer>> k,
Func<T, U, V> selector)
return (Func<V, Answer> c) =>
m(t => k(t)(y => c(selector(t, y))));
I have created a very comprehensive introduction to the Continuation monad that you can Find Here Discovering the Continuation Monad in C#
Also you can find a.Net Fiddle here
I Repeat it in summary here
Starting from an initial Function
int Square(int x )return (x * x);
- Use Callback and remove return type
public static void Square(int x, Action<int> callback)
callback(x * x);
- Curry the Callback
public static Action<Action<int>> Square(int x)
return (callback) => callback(x * x); ;
- Generalize the returned Continuation
public static Func<Func<int,T>,T> Square<T>(int x)
return (callback) => callback(x * x); ;
- Extract the Continuation Structure Also Known As the Return Method of the monad. That is Give me a value and i will give you a Monad for this value
//((U→ T) → T)
delegate T Cont<U, T>(Func<U, T> f);
public static Cont<U, T> ToContinuation<U, T>(this U x)
return (callback) => callback(x);
square.ToContinuation<Func<int, int>, int>()
- Add The bind Monadic method and thus Complete the Monad.That is Give me a Two Monads and i will combine them to a new monad
((A→ T) → T)→( A→((B→ T) → T))→ ((B→ T) → T)
public static Cont<V, Answer> Bind<T, U, V, Answer>(
this Cont<T, Answer> m,
Func<T, Cont<U, Answer>> k,
Func<T, U, V> selector)
return (Func<V, Answer> c) =>
m(t => k(t)(y => c(selector(t, y))));
edited Mar 24 at 12:42
answered Mar 24 at 12:37
Dimitris pDimitris p
195
195
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f26332494%2fc-sharp-continuation-monad-implementation%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown