Live data from Hacker News

Functor and Monad in Swift

javiersoto.me

11–20 of 20 posts

Re: Functor and Monad in Swift

#11

Nice article, well done! Minor question/comment regarding the implementation of Result.map: Why do you create a new Result in the error case? Result is immutable (or am I missing something specific to Swift here?), so the old and new Result are the same and stay that way. I'm not familiar with the internals of Swift, but e.g. in Scala, there is only one "None". If you call map or flatMap on it, the same None will alw…

enums and structs are value types (and Result is an enum) so I think that you could just return self for the error case (gaining cleanliness and a little efficiency).

Objects (of classes) are reference types so if Result was a class there would be a difference between returning self and returning a new Result.

Re: Functor and Monad in Swift

#12

This is an excellent article, I think it explains the monad pretty simply, starting from an understanding of functors. For those that are struggling with understanding (or feeling like you understand) monads, here are some articles like this one that I found very useful (note that the links are for haskell, but obviously, monads are a generally applicable concept). A visual explanation of monads: http://adit.io/posts…

Personally it clicked for me after reading "You Could Have Invented Monads"[0] and LYAH (in order as you suggest).

[0] http://blog.sigfpe.com/2006/08/you-could-have-invented-monad...

Re: Functor and Monad in Swift

#13
Can someone help me bridge the gap between this understanding of the definition of functor and the ocaml version?

In ocaml, a functor is a module that takes another module as a parameter. In this, a functor is a type that implements the map method. Is there something I'm missing that explains how both of them are functors?

Re: Functor and Monad in Swift

#14

Can someone help me bridge the gap between this understanding of the definition of functor and the ocaml version? In ocaml, a functor is a module that takes another module as a parameter. In this, a functor is a type that implements the map method. Is there something I'm missing that explains how both of them are functors?

The simple explanation is that the word functor is being used for two different concepts.

I found this question on Stackoverflow.

http://stackoverflow.com/questions/16353066/how-are-functors...

Re: Functor and Monad in Swift

#15
post #2

This is a great article. It captures the essence of functors and monads in programming really well without the usual nonsensical analogies from other similar tutorials. There are just a few tiny pieces missing from the puzzle: the functor and monad laws. They're pretty straight-forward - one would think they're common sense. For functor, there is the mapping with identity law: functor.map({ $0 }) == functor which say…

Thanks!

I think that would make for another interesting article. I purposely ignored those details to make sure I kept my article more practical and less academic :) I also didn't mention the unit function of Monads (is that equivalent to one of the laws that you refer to?)

Re: Functor and Monad in Swift

#16

Nice article, well done! Minor question/comment regarding the implementation of Result.map: Why do you create a new Result in the error case? Result is immutable (or am I missing something specific to Swift here?), so the old and new Result are the same and stay that way. I'm not familiar with the internals of Swift, but e.g. in Scala, there is only one "None". If you call map or flatMap on it, the same None will alw…

I'm not familiar with swift, but in Haskell, you can't write the following: flatMap :: Either e a -> (a -> Either e b) -> Either e b flatMap x f = case x of Left _ -> x Right x' -> f x' In the case expression, you have to write `Left err -> Left err`, because `x` here has the type `Either e a`, but `Either e b` is expected.

Yeah, this is correct. This would be wrong:

    func map(f: T -> U) -> Result {
        switch self {
        case let .Value(value):
            return Result.Value(Box(f(value.unbox)))
        case let .Error(error):
            // self is Result, but the return type must be Result
            return self
        }
    }

Re: Functor and Monad in Swift

#17

Nice article, well done! Minor question/comment regarding the implementation of Result.map: Why do you create a new Result in the error case? Result is immutable (or am I missing something specific to Swift here?), so the old and new Result are the same and stay that way. I'm not familiar with the internals of Swift, but e.g. in Scala, there is only one "None". If you call map or flatMap on it, the same None will alw…

enums and structs are value types (and Result is an enum) so I think that you could just return self for the error case (gaining cleanliness and a little efficiency). Objects (of classes) are reference types so if Result was a class there would be a difference between returning self and returning a new Result.

I agree that it would be a little cleaner, because it would express the intention better (the fact that you're simply giving out the same error). However, the type would be wrong:

Yeah, this is correct. This would be wrong:

    func map(f: T -> U) -> Result {
        switch self {
        case let .Value(value):
            return Result.Value(Box(f(value.unbox)))
        case let .Error(error):
            // self is Result, but the return type must be Result
            return self
        }
    }
As for efficiency: like you mention, enum are value types. For this reason, they're passed by copy! So even returning self would return a copy of self, not the same instance :)

Re: Functor and Monad in Swift

#18
post #17

Earlier quoted context omitted.

enums and structs are value types (and Result is an enum) so I think that you could just return self for the error case (gaining cleanliness and a little efficiency). Objects (of classes) are reference types so if Result was a class there would be a difference between returning self and returning a new Result.

I agree that it would be a little cleaner, because it would express the intention better (the fact that you're simply giving out the same error). However, the type would be wrong: Yeah, this is correct. This would be wrong: func map (f: T -> U) -> Result { switch self { case let .Value(value): return Result .Value(Box(f(value.unbox))) case let .Error(error): // self is Result , but the return type must be Result retu…

Good point. I missed that. Trouble with reading blog posts is getting relevant bits of code together on the screen, should have opened a second browser window (or third to include the HN discussion).

Value types are actually copy on write internally in Swift so no copy will be done unless a mutation of the error is attempted.

Re: Functor and Monad in Swift

#19
post #17

Earlier quoted context omitted.

I agree that it would be a little cleaner, because it would express the intention better (the fact that you're simply giving out the same error). However, the type would be wrong: Yeah, this is correct. This would be wrong: func map (f: T -> U) -> Result { switch self { case let .Value(value): return Result .Value(Box(f(value.unbox))) case let .Error(error): // self is Result , but the return type must be Result retu…

Good point. I missed that. Trouble with reading blog posts is getting relevant bits of code together on the screen, should have opened a second browser window (or third to include the HN discussion). Value types are actually copy on write internally in Swift so no copy will be done unless a mutation of the error is attempted.

Oh yeah that's a good point! (and a really interesting optimization that can be applied to immutable values)

Re: Functor and Monad in Swift

#20
post #17

Earlier quoted context omitted.

enums and structs are value types (and Result is an enum) so I think that you could just return self for the error case (gaining cleanliness and a little efficiency). Objects (of classes) are reference types so if Result was a class there would be a difference between returning self and returning a new Result.

I agree that it would be a little cleaner, because it would express the intention better (the fact that you're simply giving out the same error). However, the type would be wrong: Yeah, this is correct. This would be wrong: func map (f: T -> U) -> Result { switch self { case let .Value(value): return Result .Value(Box(f(value.unbox))) case let .Error(error): // self is Result , but the return type must be Result retu…

Yep, you are right.

I looked deeper into the Scala implementation of Option [1] to see how Scala achieves that, and whether I can port their implementation to Swift.

Long story short: Scala has a bottom type [2], Swift does not, therefore the Scala-implementation can not be ported to Swift.

A bit more detail: In Scala, Some and None are not enum-Values (as in Swift), but there is an abstract class called Option which Some and None inherit from. Option is a generic class. None is not generic anymore (this alone isn't possible in Swift!), but is an Option[Nothing]. Nothing is the bottom type: it can be returned for any Option[U], because Nothing "inherits" from all classes, and therefore also from U.

OK, that was still pretty short - if anyone is interested in a longer write-up including code, please let me know and I'll write a blog post :-)

[1] https://github.com/scala/scala/blob/838ff2c2f256d1c114a406ff...

[2] http://en.wikipedia.org/wiki/Bottom_type

Post reply on HN