typelift / swiftz Goto Github PK
View Code? Open in Web Editor NEWFunctional programming in Swift
License: BSD 3-Clause "New" or "Revised" License
Functional programming in Swift
License: BSD 3-Clause "New" or "Revised" License
I'm curious about the recommended way to install this into a project. I currently have the projects in my workspace but it seems that you recommend to "Build the .framework". Can you elaborate on how you do this?
It's a bit shifting assignment operator.
var a = 1
a <<= 1 // a is 2
a >>= 1 // a is 1
Is there a particular reason (other than it being the standard) that >>= was reused as bind? Should it be changed to something else? e.g. >>>
(I may have missed commentary on this already, however I couldn't find any). Cheers.
So, there was a bigish pull request #105 for rejigging things to merge into https://github.com/typelift/Basis. That was closed without merging. Would it be possible for someone to explain, probably best on the readme, the relationship between the projects and modules?
Code example shows (but does not compile due to error):
let xs = [1, 2, 0, 3, 4]
// we can use the Min semigroup to find the minimal element in xs
sconcat(Min(), 2, xs) // 0
// we can use the Sum monoid to find the sum of xs
mconcat(Sum<Int8, NInt8>(i: { return nint8 }), xs) // 10
but in order to compile with Xcode 6 beta 3 xs must be array of Int8.
Compiles:
let xs: [Int8] = [1, 2, 0, 3, 4]
// we can use the Min semigroup to find the minimal element in xs
sconcat(Min(), 2, xs) // 0
// we can use the Sum monoid to find the sum of xs
mconcat(Sum<Int8, NInt8>(i: { return nint8 }), xs) // 10
Add an explanation of how to use Type Equality. Maybe as a blog style post in the wiki.
If anyone wants to give this a shot, I will help build on it.
Also, update the README with the new content.
Also, link to the RAC examples. They are pretty good examples.
I'm a bit confused on how JArray
and JDictionary
are supposed to be used.
Suppose I have a JSON response that looks like this:
[
{ "post": { "title": "foo", "body": "..." }},
{ "post": { "title": "foo", "body": "..." }},
{ "post": { "title": "foo", "body": "..." }},
]
And a class like this:
class Post : JSONDecode {
var title: String?
var body: String?
typealias J = Post
class func fromJSON(x: JSValue) -> Post? {
switch x {
case let .JSObject(d):
let post = Post()
post.title = d["title"] >>= JSString.fromJSON
post.body = d["body"] >>= JSString.fromJSON
default: return nil
}
}
I have this pesky "post" key repeated in the response, so it seems to complicate things a bit.
Is there a way to extract this to post objects directly? Or do I need to first manually pull out the inner dictionary and call Post.fromJSON
on those to get my [Post]
result?
It's currently:
func curry<A, B, C>(f: (A, B) -> C, a: A, b: B) -> C
I think it should be
func curry<A, B, C>(f: (A, B) -> C) -> A -> B -> C
Why is it not?
So I started a repo for a set implementation here, and I though to possibly include it in this repo, though I don't want to just pile a bunch of stuff on that is not needed or should not be part of this repo.
Thoughts?
Monoid Protocol Is actually pretty nice to write
operator infix <> {}
protocol Monoid {
typealias M
func mzero()->M
@infix func <> (M,M)->M
}
Under the testing group there is a SwiftCheck.swift file that is referenced but not actually in the project. It might have gotten added to the project but not actually copied in.
The Futures/Promises implementation would be nice if it was more complete. Have you taken a look at https://github.com/Thomvis/BrightFutures? Perhaps we can merge the two projects?
Cocoapod distribution will reduce the barrier for some of us to try out swiftz. Is this in swiftz future?
We don't have any instances of Comonad in the framework. I'm starting to think it would be better served in a new framework in the same vein as Category-Extras where we can better flesh out these ideas. If not, it would be trivial to write a Comonad instance for at least Box. What do you think?
They should be possible, but there seems to be bugs with recursive types.
If they can implement Functor
is another problem.
Swift already has native support for optional values. Why duplicate this with Maybe
? Couldn't you just define map
for T?
?
Add Bifunctor
leftMap
, rightMap
and bimap
. Put it in the global scope.
Add instances for Either
and Const
. Try to add an instance for (,)
.
Explain why there is no instance for Map
.
http://hackage.haskell.org/package/bifunctors-4.1.1.1/docs/Data-Bifunctor.html
I have a dictionary that contains the key "events". This key contains an array of dictionaries.
I use JSValue.decode(data)
on the response data and that returns a JSValue.JSObject
. So now I use a switch do get the object and parse the "events" key into a JSValue.JSArray
by doing:
switch json {
case let .JSObject(d):
let events = d["events"] >>= JArray.fromJSON
//... etc
However, this will not compile. I receive the error: "NSString is not a subtype of DictionaryIndex" which I've come to understand just means there is a type mismatch somewhere in that statement. How should I be using JArray
to get an array of dictionaries?
I'm trying to use just a couple pieces of this framework in a project, but adding JSON.swift to the project means that JavaScriptCore's JSValue types are no longer accessible.
How would you feel about renaming JSValue & its ilk to JSONValue? (Or do you think there's a better way to solve this issue?)
Hey guys,
I'm the author of Twitter's Bijection library in Scala, and have found the Injection and Bijection typeclasses to be extremely useful. I'd love to get these, and a few other typeclasses, into swiftz. Here's some extremely early playing around:
// Playing around with the Injection typeclass.
protocol Injection {
typealias T
typealias U
func apply(T) -> U
func invert(U) -> T?
}
class IntInjection: Injection {
func apply(i: Int) -> String {
return String(i)
}
func invert(s: String) -> Int? {
return s.toInt()
}
}
let i = IntInjection()
i.apply(10)
i.invert("10")
Would you guys be interested in taking this pull req? I don't want to send it over if this is beyond the library scope.
One other Q:
Swiftz no longer compiles on the latest Xcode beta, as the List.lookup() function "references a local function from another local function."
The JSON objects should be traversable by lenses (, prisms and traversals).
We should also consider zippers with error reporting, like in Argonaut.
Radar submitted.
Radar: 17377676
With https://github.com/maxpow4h/swiftz/blob/54870ca7b81a2595b3707646cba4d83a71bb6667/swiftz/TypeEquality.swift and https://github.com/maxpow4h/swiftz/blob/54870ca7b81a2595b3707646cba4d83a71bb6667/swiftz/List.swift#L47-L56 you can show Int =:= String
and define the function:
func apply(a: Int) -> String {
return a
}
that correctly type checks, showing unsoundness.
Commentary:
It appears swift isn't fully obeying the type constraints provided in where clauses.
With these 2 problems:
I propose explicitly providing FA and FB and writing lots of code.
Alternatively, in xsharpx and functional java, you just write map on everything and don't inherit.
I'm not sure what is the best approach. Ideas?
In the absence of option members of a protocol, a right biased Those is very useful. Especially to call cata on.
Does this sound about right to everyone?
There are many errors related to the literal convertible protocols being changed to use initializers rather than static methods, e.g.:
swiftz_core/swiftz_core/List.swift:102:1: Type 'List<A>' does not conform to protocol 'ArrayLiteralConvertible
When I've fixed those, though, I reach some more intractable errors, e.g. they've disabled extensions of generic types in different modules altogether:
swiftz/OptionalExt.swift:11:15: Extension of generic type 'Optional<T>' from a different module cannot provide public declarations
I want to define the notion of an action of one type on another. For instance, the CoreGraphics type CGVector represents a 2D vector, and CGPoint represents a point on the coordinate plane. There should be a function
@infix |> (v: CGVector, p: CGPoint) -> CGPoint
that translates the point p by the vector v. I'd like to implement this as a protocol:
protocol Action {
typealias A
typealias M
@infix |> (a: A, x: M) -> M
}
and instantiate it by extension to the pair (CGVector, CGPoint)
, but I get the error
Non-nominal type '(CGVector, CGPoint)' cannot be extended.
I can't think of a good workaround for this.
In Idris, I could implement this with a multiparameter typeclass:
class Action a m where
(|>) : a -> m -> m
and then instantiate it as
instance Action CGVector CGPoint where
(mkCGVector a b) |> (mkCGPoint c d) = mkCGPoint (a + c) (b + d)
where mkCGVector
and mkCGPoint
are the sole constructors of CGVector
and CGPoint
, respectively
An array (with array syntax) with the same functions as Array
, except all the functions return new arrays.
It's currently:
func flip<A, B, C>(f: ((A, B) -> C), b: B, a: A) -> C
I think it should be
func flip<A, B, C>(f: (A, B) -> C)(b: B, a: A) -> C
Why is it not?
I think a LOT of folks would wind up getting involved pretty fast
(question, not bug)
Why build Future
on pthreads rather than GCD queues (which is what Apple optimizes to)? Do you help with that piece (looks like ExecutionContext is TBD)? Swiftz should definitely avoid spinning up any full threads, since that's a lot of overhead compared to a queue. (very interesting start btw)
equal
doesn't work on Dictionary
. It should!
A minimal swiftz library with type level primitives missing from the standard library.
Could be distributed as a single file, called Prelude?
The consumers of the core should expect to link with the full framework if they want to start writing instances of these typeclasses. Besides, if all you need is Box and a few combinators, there's really not much you should be doing with a Bifunctor instance of Const.
Could you update the readme with more detailed info on how to consume a framework. I know it's not an issue with your code (it's my issue as an XCode beginner). I just can't ever figure out how to consume frameworks. Apple makes it seem as if you just drag and drop (which appears to work until you actually try to build and the linker yells at you)
I'm trying to follow your instructions on your readme.
The way things stand I get a linker error: swiftz framework cannot be found.
Thanks for any pointers to documentation that will get me on the right track. Would really love to be able to play around with Swiftz.
2014-11-01 11:14:37.419 xctest[3562:119069] The test bundle at /Users/mgwelch/Library/Developer/Xcode/DerivedData/swiftz-dfchxmsrsusopsgocnqvrawwpzyp/Build/Products/Debug/swiftz_coreTests.xctest could not be loaded because an unanticipated error occurred.
2014-11-01 11:14:37.419 xctest[3562:119069] Detailed error information: Error Domain=NSCocoaErrorDomain Code=3587 "The bundle “swiftz_coreTests” couldn’t be loaded because it is damaged or missing necessary resources." (dlopen_preflight(/Users/mgwelch/Library/Developer/Xcode/DerivedData/swiftz-dfchxmsrsusopsgocnqvrawwpzyp/Build/Products/Debug/swiftz_coreTests.xctest/Contents/MacOS/swiftz_coreTests): Library not loaded: @rpath/libswiftAppKit.dylib
Referenced from: /Users/mgwelch/Library/Developer/Xcode/DerivedData/swiftz-dfchxmsrsusopsgocnqvrawwpzyp/Build/Products/Debug/swiftz_core.framework/Versions/A/swiftz_core
Reason: image not found) UserInfo=0x1005002a0 {NSLocalizedFailureReason=The bundle is damaged or missing necessary resources., NSLocalizedRecoverySuggestion=Try reinstalling the bundle., NSFilePath=/Users/mgwelch/Library/Developer/Xcode/DerivedData/swiftz-dfchxmsrsusopsgocnqvrawwpzyp/Build/Products/Debug/swiftz_coreTests.xctest/Contents/MacOS/swiftz_coreTests, NSDebugDescription=dlopen_preflight(/Users/mgwelch/Library/Developer/Xcode/DerivedData/swiftz-dfchxmsrsusopsgocnqvrawwpzyp/Build/Products/Debug/swiftz_coreTests.xctest/Contents/MacOS/swiftz_coreTests): Library not loaded: @rpath/libswiftAppKit.dylib
Referenced from: /Users/mgwelch/Library/Developer/Xcode/DerivedData/swiftz-dfchxmsrsusopsgocnqvrawwpzyp/Build/Products/Debug/swiftz_core.framework/Versions/A/swiftz_core
Reason: image not found, NSBundlePath=/Users/mgwelch/Library/Developer/Xcode/DerivedData/swiftz-dfchxmsrsusopsgocnqvrawwpzyp/Build/Products/Debug/swiftz_coreTests.xctest, NSLocalizedDescription=The bundle “swiftz_coreTests” couldn’t be loaded because it is damaged or missing necessary resources.}
2014-11-01 11:14:37.420 xctest[3562:119069] Usage: xctest [-XCTest Self | All | None | ]
2014-11-01 11:14:37.420 xctest[3562:119069] Couldn't posix_spawn: error 8
So, if I have a type A: JSONDecode
, I believe that I should be able to decode a list of them by calling JArray<A,A>.fromJSON
. but, this requires A:JSON
which seems odd since toJSON isn't needed at all.
It seems that swiftz's targets are configured to generate libraries for a OSX target. I'm trying to use it in an iOS app. iOS build targets would greatly facilitate this.
I think this is going to be just a lot of pasting public
everywhere. Also, removing @
from @final
and other similar keywords.
A few notes on housekeeping for the framework:
Right now we're using both tabs, two, and four spaces per indent. I'd prefer tabs if it's all the same.
(#flamewar)
It is confusing as all hell to get this framework set up properly because we don't have two different projects for the iOS and OS X versions of this framework. To remedy the situation, I'd just revise the project to use the structure I've got in the other frameworks under typelift:
- An OS X project
- An iOS project
- A unified workspace
All target names resolve to just swiftz
and swiftz_core
instead of swiftz_ios
, and swiftz_core_ios
this way. And it keeps Xcode sane. Currently, when you try to add the framework to "copy files" it pulls both and makes the linker vomit if you pick the wrong one (i.e. the one that shows in build/Debug[-iphoneos]
in tiny gray text). There should only be two visible options when you use this thing, and this is the only way to enforce it. The only downside is new files have to be put into both xcode projects, but that's what the big workspace is for anyways.
Looks like it hasn't been updated in a while. Perhaps a rewrite is in order. The installation instructions are bare and rather draconian.
Swift has an... interesting approach to numeric protocols. It's a real helter-skelter mix of some that add operations, make things integer-y, make things floating-point-y, signal access times for collections-y, etc. What it doesn't do is actually define a good hierarchy of the values their numeric structures can represent. I think we can fix that.
The NInt et al machinery can be collapsed and reappropriated for arbitrary precision arithmetic (somehow. GMP, OpenSSL, CommonCrypto?). We can define proper numeric type classes and conformances for swift types and get real numeric constraints going for once.
would that be topical? I'm happy to burn a few days trying to port some heavily diluted simplified versions of my numerical haskell tech over to swift
Per my previous issue, I'm trying to define an action of CGVector
on CGPoint
, both of which are semantically just pairs of floats. I can define the desired action as
@infix func |> (v: CGVector, p: CGPoint) -> CGPoint {
return CGPoint(x: v.dx + p.x, y: v.dy + p.y)
}
but obviously the more functional approach would be to pattern match. Unfortunately, even though CGVector and CGPoint are just product types (they are structs with two Floats in them), Swift doesn't seem to want to pattern match on their constructors. For example, if I do
func foo(a: CGVector) -> Float {
switch a {
case let CGVector(x, y): return x + y
}
}
I get the following error:
<REPL>:5:27: error: pattern variable binding cannot appear in an expression
case let CGVector(x, y): return x + y
^
If I define a function using the built-in tuple type, it works fine:
func bar(a: (Float, Float)) -> Float {
switch a {
case let (x, y): return x + y
}
}
There seems to be an asymmetry in Swift between sum types (enums), which work fine in pattern matching, and product types (structs), which don't. Is there any way to create a product type other than the standard tuple that will work for pattern matching?
Just a heads up before I remove this thing. It looks like everything inside has been merged, but I'll give this issue 48 hours. If you see anything on it you want to preserve, speak up!
I know the translation of a JSON null to NSNull is what a lot of JSON libraries do, but I think this creates a lot of issues that are never tested for (because a null value could come from the server anywhere in the JSON someday after the app is developed) - it's guaranteed to fail to store properly into any CoreData object you try to assign it to, or to parse correctly if you are trying to use integerValue to populate a numeric property. A better idea I think is to translate JSON null as an empty string where it can do much less harm.
What is the benefit of having a separate Result type instead of using Either with NSError to the left?
I'm beginning to wonder if it would be beneficial to section each of our operators manually so we can avoid explicit lambdas. Because Swift doesn't allow us to use curried operators (yet?), I'm thinking we re-declare each of our infix operators with postfix and prefix curried versions that admit left and right application respectively.
A classic example of basic Haskell is
let l = [1..10]
> [1,2,3,4,5,6,7,8,9,10]
map (+5) l
> [6,7,8,9,10,11,12,13,14,15]
In Swift, that currently looks like this
let l = [Int](1...10)
l.map({ x in x + 5 })
But if we introduce prefix + as a sectioned operator
prefix func +<A : protocol<IntegerLiteralConvertible, IntegerArithmeticType>>(l : A) -> (A -> A) {
return { r in l + r }
}
that example becomes
let l = [Int](1...10)
l.map(+5)
The question, then, is this: Is currying operators for a more declarative approach worth polluting the global operator namespace with 2 more copies of each function?
I'm interested in learning both swiftz and sleipnir and discovered something odd on my very first test:
import Foundation
import Sleipnir
import swiftz_core
class flipSpec : SleipnirSpec {
var spec : () = describe("flip: (A -> B -> C) -> B -> A -> C") {
it("Takes a function and returns identical function but with arguments flipped") {
let subtract = { (x:Int) in { (y:Int) in x-y }}
let flipSubtract = flip(subtract);
flipSubtract(5)(3).should.equal(subtract(3)(5));
}
}
}
2 compiler errors on the last line:
/Users/mgwelch/Documents/Projects/thirdparty/swiftz/swiftz_core/swiftz_coreTests/FunctionSpecs.swift:18:26: Missing argument label 'b:' in call
/Users/mgwelch/Documents/Projects/thirdparty/swiftz/swiftz_core/swiftz_coreTests/FunctionSpecs.swift:18:29: Missing argument label 'a:' in call
I don't have a
or b
in my function definition so it appears to be referring to the a
and b
in the definition of flip
. Indeed, if I change the parameter names to q
and r
then the compiler errors change. What is odd is that if I put explicit underscores in the definition of flip
then I get compiler warnings because the underscore is unnecessary.
Do you think this is a compiler issue and I should file a radar?
Stuff is going to get pretty wild without macros.
Maybe we can leverage the CPP for now?
Edit: will leave this issue till later
theres a declaration syntax
extension TypeName : ProtocolName {
declaration here
}
If let x = mx {
return f(x)
} else {
return null
}
Or similar, gets rid of the need for the (!) operator.
quite a few changes. working on a pull request.
A[]
to [A]
CConstPointer
references to UnsafePointer
sA declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.