Defining a generic unfoldr function - swift

func unfoldr<A, B>(_ f: #escaping (B) -> (A, B)?) -> (B) -> UnfoldFirstSequence<A> {
return { b in sequence(
first: b, next: { x in
switch f(x) {
case .some(let(a, b)):
return Optional(a)
default:
return Optional.none
}
}
)
}
}
With this definition, I am getting the following error:
Cannot convert value of type 'B' to expected argument type 'A'.
Is there some way of solving this issue and definining this function ?

Your sequence doesn't seem to be a UnfoldFirstSequence. Your sequence seems to have a state B, and f is responsible for producing a new state and an element for the sequence. An UnfoldFirstSequence has no state that you can control. You can only produce the next element from the previous element.
Your sequence can be modelled by the more general UnfoldSequence, which has a State generic parameter. In fact, an UnfoldFirstSequence<T> is just an UnfoldSequence<T, (T?, Bool)>! See why the former is a special case of the latter by reading the source code :)
You can create such a sequence using sequence(state:next:).
func unfoldr<A, B>(_ f: #escaping (B) -> (A, B)?) -> (B) -> UnfoldSequence<A, B> {
return {
sequence(state: $0) { x in
guard let (a, b) = f(x) else {
return nil
}
x = b
return a
}
}
}
Example:
let seq = unfoldr { x -> (String, Int)? in
if x == 10 {
return nil
} else {
return ("\(x)", x + 1)
}
}
seq(0).forEach { print($0) }

Related

How to have a function returning 1 value in some circumstances return 2 or 3 values and vice-versa?

I'm new to Swift. Is it possible to have a function return by standard only 1 value and in some circumstances 2 or 3 values ?
You can return a tuple:
func functionThatReturnsTuple(numberOfElementsToReturn: Int) -> (String?, Int?) {
if numberOfElementsToReturn == 1 {
return ("One", nil)
}
if numberOfElementsToReturn == 2 {
return ("One", 2)
}
return (nil, nil)
}
You can return array:
func functionThatReturnsArray(numberOfElementsToReturn: Int) -> [String] {
if numberOfElementsToReturn == 3 {
return ["One", "Two", "Three"]
}
....
return []
}
Notice that both examples use optionals, make sure to handle them .
Alternatively you can use enum:
enum Value<A, B, C> {
case single(A)
case pair(A, B)
case triplet(A, B, C)
}
func yourFunc<A, B, C>(numberOfParameters: Int) -> Value<A, B, C> {
// determine how many params you need to return, and return them
}
And inn your outer code just check Value's case with switch of if case.

Generic factory method and type inference

I have the following class with a generic factory method:
final class Something<T> {
let value: T
init(initial: T) {
value = initial
}
}
extension Something {
class func zip<A, B>(_ a: A, _ b: B) -> Something<(A, B)> {
let initial = (a, b)
return Something<(A, B)>(initial: initial)
}
}
How come I can’t call zip without explicitly specifying the return type?
// ERROR: Cannot invoke `zip` with an argument list of type `(Int, Int)`
let y = Something.zip(1, 2)
// OK: Works but it’s unacceptable to require this on caller's side
let x = Something<(Int, Int)>.zip(1, 2)
Thank you for your time!
The reason you're seeing this is that there's nothing in this call:
let y = Something.zip(1, 2)
That tells Swift what T should be.
Your call implicitly specifies what A and B should be, and specifies the method should return Something<A, B>. But that Something<A, B> is not connected to Something<T>.
In fact, nothing at all in your call is connected to T; T is left unspecified, so it could be anything. I mean that literally—you can actually put (nearly) any random type in the angle brackets after Something and it'll work exactly the same:
let y = Something<UICollectionViewDelegateFlowLayout>.zip(1, 2)
What you would really like to do is somehow specify that T has to be a tuple and the two parameters are of the same types as the tuple's elements. Unfortunately, Swift doesn't currently have the features needed to properly do that. If the language were more sophisticated, you could say something like this:
extension<A, B> Something where T == (A, B) {
class func zip(a: A, _ b: B) -> Something {
let initial = (a, b)
return Something(initial: initial)
}
}
But for now, you'll have to make do with this horrible hack, which works by meaninglessly reusing the T type parameter so that it's no longer at loose ends:
extension Something {
class func zip<B>(a: T, _ b: B) -> Something<(T, B)> {
let initial = (a, b)
return Something<(T, B)>(initial: initial)
}
}
In short explanation, you use generics not correct. It's not realtime feature, it's precompile thing. If you need to make abstract class from generic input values, see and do like this:
class Abstract<T> {
init(value: T) {
print("inputed value: \(value)")
}
}
class Something {
class func zip<A, B>(value: A, value2: B) -> Abstract<(A, B)> {
print("Something.zip", value, value2)
return Abstract<(A, B)>(value: (value, value2))
}
}
Something.zip(5, value2: 40) // "inputed value: (5, 40)"
T simply isn't related to A and B in that way and so can't be inferred.
Eg.
let z = Something<(String, String)>.zip(1, 2)
let z2 = Something<AnyObject>.zip(1, 2)
work just fine to return a Something<(Int, Int)>
You can introduce type inference for your case like this:
final class Something<T> {
let value: T
init(initial: T) {
value = initial
}
class func zip<A, B>(_ a: A, _ b: B) -> Something<T> where T == (A, B) {
let initial = (a, b)
return Something<(A, B)>(initial: initial)
}
}
let y = Something.zip(1, 2) //works

How to extension HalfOpenInterval with reduce method

I hope to extension HalfOpenInterval with reduce method
so can easy use some quick code snippet
for example:
var a = [3,4,9,7]
var mini = (0..<a.count).reduce(0, combine: { a[$0] > a[$1] ? $0 : $1 })
I notice that HalfOpenInterval fit IntervalType protocol, but not sure how to iterative each element in reduce function
extension HalfOpenInterval {
func reduce<T>(initialize: T, combine: (u: U, t:T) -> U) -> U {
...
}
}
tks
Maybe, what you should extend is Range:
extension Range {
func reduce<U>(initial:U, combine:(U, T) -> U) -> U {
return Swift.reduce(self, initial, combine)
}
}
let sum = (0 ..< 12).reduce(0, combine: { $0 + $1}) // -> 66
HalfOpenInterval or ClosedInterval is not for that, because it has only "start" and "end" values, but does not have "stride" of each values. Something like this:
Range also has "start" and "end", and these values itself know the next value of them:
Another similar structure, StrideTo and StrideThrough which constructed with stride(from:to:by:) or stride(from:through:by). It also has "start" and "end", and in this case, structure itself knows the "stride" between values.
You can extend the Range class in the following way.
extension Range {
func reduce<U>(initialize: U, combine: (u: U, t:T) -> U) -> U {
var result = initialize
for value in self {
result = combine(u: result,t: value)
}
return result
}
}

Avoid consecutive "if let" declarations in Swift [duplicate]

This question already has answers here:
Using multiple let-as within a if-statement in Swift
(3 answers)
Closed 6 years ago.
In Swift I used if let declarations to check if my object is not nil
if let obj = optionalObj
{
}
But sometimes, I have to face with consecutive if let declarations
if let obj = optionalObj
{
if let a = obj.a
{
if let b = a.b
{
// do stuff
}
}
}
I'm looking for a way to avoid consecutive if let declarations.
I would try something like :
if let obj = optionalObj && if let a = obj.a && if let b = a.b
{
// do stuff
}
But the swift compiler do not allow this.
Any suggestion ?
Update
In swift 1.2 you can do
if let a = optA, let b = optB {
doStuff(a, b)
}
Original answer
In your specific case, you can use optional chaining:
if let b = optionaObj?.a?.b {
// do stuff
}
Now, if you instead need to do something like
if let a = optA {
if let b = optB {
doStuff(a, b)
}
}
you're out of luck, since you can't use optional chaining.
tl; dr
Would you prefer a cool one-liner instead?
doStuff <^> optA <*> optB
Keep reading. For how scaring it might look, this is really powerful and not so crazy to use as it seems.
Fortunately, this is a problem easily solved using a functional programming approach. You can use the Applicative abstraction and provide an apply method for composing multiple options together.
Here's an example, taken from http://robots.thoughtbot.com/functional-swift-for-dealing-with-optional-values
First we need a function to apply a function to an optional value only only when it contains something
// this function is usually called fmap, and it's represented by a <$> operator
// in many functional languages, but <$> is not allowed by swift syntax, so we'll
// use <^> instead
infix operator <^> { associativity left }
func <^><A, B>(f: A -> B, a: A?) -> B? {
switch a {
case .Some(let x): return f(x)
case .None: return .None
}
}
Then we can compose multiple options together using apply, which we'll call <*> because we're cool (and we know some Haskell)
// <*> is the commonly-accepted symbol for apply
infix operator <*> { associativity left }
func <*><A, B>(f: (A -> B)?, a: A?) -> B? {
switch f {
case .Some(let value): return value <^> a
case .None: return .None
}
}
Now we can rewrite our example
doStuff <^> optA <*> optB
This will work, provided that doStuff is in curried form (see below), i.e.
func doStuff(a: A)(b: B) -> C { ... }
The result of the whole thing is an optional value, either nil or the result of doStuff
Here's a complete example that you can try in the playground
func sum(a: Int)(b: Int) -> Int { return a + b }
let optA: Int? = 1
let optB: Int? = nil
let optC: Int? = 2
sum <^> optA <*> optB // nil
sum <^> optA <*> optC // Some 3
As a final note, it's really straightforward to convert a function to its curried form. For instance if you have a function taking two parameters:
func curry<A, B, C>(f: (A, B) -> C) -> A -> B -> C {
return { a in { b in f(a,b) } }
}
Now you can curry any two-parameter function, like + for example
curry(+) <^> optA <*> optC // Some 3
I wrote a little essay on the alternatives some time ago: https://gist.github.com/pyrtsa/77978129090f6114e9fb
One approach not yet mentioned in the other answers, which I kinda like, is to add a bunch of overloaded every functions:
func every<A, B>(a: A?, b: B?) -> (A, B)? {
switch (a, b) {
case let (.Some(a), .Some(b)): return .Some((a, b))
default: return .None
}
}
func every<A, B, C>(a: A?, b: B?, c: C?) -> (A, B, C)? {
switch (a, b, c) {
case let (.Some(a), .Some(b), .Some(c)): return .Some((a, b, c))
default: return .None
}
}
// and so on...
These can be used in if let statements, case expressions, as well as optional.map(...) chains:
// 1.
var foo: Foo?
if let (name, phone) = every(parsedName, parsedPhone) {
foo = ...
}
// 2.
switch every(parsedName, parsedPhone) {
case let (name, phone): foo = ...
default: foo = nil
}
// 3.
foo = every(parsedName, parsedPhone).map{name, phone in ...}
Having to add the overloads for every is boilerplate'y but only has to be done in a library once. Similarly, with the Applicative Functor approach (i.e. using the <^> and <*> operators), you'd need to create the curried functions somehow, which causes a bit of boilerplate somewhere too.
In some cases you can use optional chaining. For your simple example:
if let b = optionalObj?.a?.b {
// do stuff
}
To keep your nesting down and to give yourself the same variable assignments, you could also do this:
if optionalObj?.a?.b != nil {
let obj = optionalObj!
let a = obj.a!
let b = a.b!
}
After some lecture thanks to Martin R, I found an interesting workaround: https://stackoverflow.com/a/26012746/2754218
func unwrap<T, U>(a:T?, b:U?, handler:((T, U) -> ())?) -> Bool {
switch (a, b) {
case let (.Some(a), .Some(b)):
if handler != nil {
handler!(a, b)
}
return true
default:
return false
}
}
The solution is interesting, but it would be better if the method uses variadic parameters.
I naively started to create such a method:
extension Array
{
func find(includedElement: T -> Bool) -> Int?
{
for (idx, element) in enumerate(self)
{
if includedElement(element)
{
return idx
}
}
return nil
}
}
func unwrap<T>(handler:((T...) -> Void)?, a:T?...) -> Bool
{
let b : [T!] = a.map { $0 ?? nil}
if b.find({ $0 == nil }) == nil
{
handler(b)
}
}
But I've this error with the compiler: Cannot convert the expression's type '[T!]' to type '((T...) -> Void)?'
Any suggestion for a workaround ?

Curry Function in Swift

I want to make a function that return a curry function like below
func addTwoNumbers(a: Int)(b: Int) -> Int {
return a + b
}
addTwoNumbers(4)(b: 6) // Result: 10
var add4 = addTwoNumbers(4)
add4(b: 10) // returns 14
What is the return type of such function and how can I generate a function like this using a function that take Variadic parameters.
func generateCurry(.../*Variadic parameters*/) -> .../*curry function type*/ {
return ...//curry function
}
I want a generic solution and not take only Int as arguments in the parmeter of the generateCurry function
let curried = curry(func(a, b, c) {
print(a + b + c)
})
curried(1)(2)(3) //prints 6
You can achieve this pretty easily with closures:
/// Takes a binary function and returns a curried version
func curry<A,B,C>(f: (A, B) -> C) -> A -> B -> C {
return { a in { b in f(a, b) } }
}
curry(+)(5)(6) // => 11
let add: Int -> Int -> Int = curry(+)
add(5)(6) // => 11
It would be really nice to be able to do the same thing for functions that take 3, 4 or more arguments, but without duplicating the implementation. The signature of such a function might start something like:
/// Take a function accepting N arguments and return a curried version
func curry<T>(args: T...) -> /* ? */
What would the return type be? It would change based on the input to the function. This definitely isn't possible in Swift at the moment, and I don't think it would be possible at all without some kind of macro system. But even with macros I don't think the compiler would be satisfied unless it knew the length of the list at compile-time.
Having said that, it's really straight-forward to manually overload the currying function with a version that accepts 3, 4, 5 or more parameters:
func curry<A,B,C,D>(f: (A, B, C) -> D) -> A -> B -> C -> D {
return { a in { b in { c in f(a,b,c) } } }
}
func curry<A,B,C,D,E>(f: (A, B, C, D) -> E) -> A -> B -> C -> D -> E {
return { a in { b in { c in { d in f(a,b,c,d) } } } }
}
// etc.
I'm not sure this is actually going to be possible in the same way it is inside of languages like Python.
The core problem I see to having a single generic solution is the strong typing of the closures/funcs you want to accept.
You could fairly easily create a curry function that worked on a specific or common function signature, but as far as a general purpose curry I don't see a way for it to work. The issue is more than about the types of the arguments (as mentioned in comments) but also with the number of them.
I've written up a simple example of how you could implement a curry function. It works, but I don't see a sane way to have a truly generic one like you can in more loosely typed languages.
func add(a1: Int, a2: Int) -> Int {
return a1 + a2
}
func curry(argument: Int, block: (Int, Int) -> Int) -> Int -> Int{
func curried(arg: Int) -> Int {
return block(argument, arg)
}
return curried
}
curry(5, add)(6)
In case you want to quickly get the curry function for any number of parameters, it's possible to generate it as shown in this gist.
The code is in Swift 2.2 and generates code for Swift 2.2 (at the moment). It uses simple template-based approach (a possible alternative is constructing an AST followed by code-generation):
func genCurry(n: Int, indent: Indent = .fourSpaces, accessLevel: AccessLevel = .Default, verbose: Bool = false) -> String {
// ...
// The bulky park is skipped for clarity.
return accessLevel.asPrefix + "func curry<\(genericParams)>(f: \(fSig)) -> \(curriedSig(n)) {\n"
+ indent.single + "return \(closure)\n"
+ "}\n"
}
I recently found that currying was removed back in Swift3. I created my own version which is repetitive but does the job.
precedencegroup CurryPrecedence {
associativity: left
higherThan: MultiplicationPrecedence
}
infix operator <<== :CurryPrecedence
//1 param
func <<==<A,Z>(_ f: #escaping (A) -> (Z), _ p:A) -> () -> (Z) {
{ f(p) }
}
//2 param
func <<==<A,B,Z>(_ f: #escaping (A, B) -> (Z), _ p:B) -> (A) -> (Z) {
{ (A) in f(A,p) }
}
//3 param
func <<==<A,B,C,Z>(_ f: #escaping (A, B, C) -> (Z), _ p:C) -> (A, B) -> (Z) {
{ (A, B) in f(A,B,p) }
}
//4 param
func <<==<A,B,C,D,Z>(_ f: #escaping (A, B, C, D) -> (Z), _ p:D) -> (A, B, C) -> (Z) {
{ (A, B, C) in f(A,B,C,p) }
}
To use it:
let ten = (addTwoNumbers <<== 6 <<== 4)()
or
let ten = (addTwoNumbers <<== 6)(4)