Skip to content

Instantly share code, notes, and snippets.

@tel
Last active August 29, 2015 14:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tel/31c867008e683f8e222f to your computer and use it in GitHub Desktop.
Save tel/31c867008e683f8e222f to your computer and use it in GitHub Desktop.
Swift Compilation Segfault
func id <A>(a: A) -> A { return a }
func fix <A>(f: A -> A) -> A { return f(fix(f)) }
func loop<A>() -> A { return fix(id) }
protocol Viewl {
typealias El
func uncons() -> (El, Self)?
}
func head<X:Viewl>(x: X) -> X.El? { return x.uncons()?.0 }
func tail<X:Viewl>(x: X) -> X? { return x.uncons()?.1 }
extension String:Viewl {
typealias El = Character
func uncons() -> (Character, String)? {
return isEmpty ? nil : (self[startIndex], dropFirst(self))
}
}
extension Array:Viewl {
typealias El = Element
func uncons() -> (Array.Element, Array)? {
return isEmpty ? nil : (self[0], Array(dropFirst(self)))
}
}
class Ptr<T> { let val: T; init(_ aVal:T) { val = aVal } }
// Lazy, potentially-infinite Streams in Swift
struct Stream<A>:Viewl {
typealias El = A
let project: () -> (A, Ptr<Stream<A>>)?
init(p: () -> (A, Stream<A>)?) {
project = {
if let (a, s) = p() {
return (a, Ptr(s))
} else { return nil }
}
}
func uncons() -> (El, Stream)? {
if let (x, a) = project() {
return (x, a.val)
} else { return nil }
}
static func empty() -> Stream<A> { return Stream { nil } }
static func pure(a: A) -> Stream<A> {
return Stream { return (a, Stream.empty()) }
}
func append(s: Stream<A>) -> Stream<A> {
return Stream {
if let (a, ss) = self.uncons() {
return (a, ss.append(s))
} else { return s.uncons() }
}
}
func then<B>(f: A -> Stream<B>) -> Stream<B> {
if let (a, s) = uncons() {
return f(a).append(s.then(f))
} else { return Stream<B>.empty() }
}
}
func arrayStream<S:Viewl>(s: S) -> Stream<S.El> {
if let (x, xs) = s.uncons() {
return Stream { return (x, arrayStream(xs)) }
} else { return Stream.empty() }
}
func streamN(n: Int) -> Stream<Int> {
return Stream {
return (n, streamN(n+1))
}
}
func maybe<A,R>(z: R, f: A -> R)(m: A?) -> R {
if let a = m { return f(a) } else { return z }
}
func viewN<S:Viewl>(n: Int)(s: S) -> [S.El] {
var res:[S.El] = []
var s_ = s
for i in 1..<n {
if let (a, ss) = s_.uncons() {
res += a
s_ = ss
} else { break }
}
return res
}
@PowerUser-
Copy link

Problem was with construction of empty. Try as

func id  <A>(a: A)      -> A { return a }
func fix <A>(f: A -> A) -> A { return f(fix(f)) }
func loop<A>()          -> A { return fix(id) }

protocol Viewl {
    typealias El
    func uncons() -> (El, Self)?
}

func head<X:Viewl>(x: X) -> X.El? { return x.uncons()?.0 }
func tail<X:Viewl>(x: X) -> X?    { return x.uncons()?.1 }

extension String:Viewl {
    typealias El = Character
    func uncons() -> (Character, String)? {
        return isEmpty ? nil : (self[startIndex], dropFirst(self))
    }
}

extension Array:Viewl {
    typealias El = Element
    func uncons() -> (Array.Element, Array)? {
        return isEmpty ? nil : (self[0], Array(dropFirst(self)))
    }
}

class Ptr<T> { let val : T; init(_ aVal:T) { val = aVal } }

// Lazy, potentially-infinite Streams in Swift
struct Stream<A>: Viewl {
    typealias El      = A
    let project: () -> (A, Ptr<Stream<A>>)?

    func uncons() -> (El, Stream)? {
        if let (x, a) = project() {
            return (x, a.val)
        } else { return nil }
    }

    func append(s: Stream<A>) -> Stream<A> {
        return Stream {
            if let (a, s) = self.uncons() {
                return loop()
            } else { return s.project() }
        }
    }

    static func empty() -> Stream<A> {
      return Stream(project: { nil })
    }

    static func pure(a: A) -> Stream<A> {
        return Stream { return (a, Ptr(Stream.empty())) }
    }

    func then<B>(f: A -> Stream<B>) -> Stream<B> {
        if let (a, s) = uncons() {
            return f(a).append(s.then(f))
        } else { return Stream<B>.empty() }
    }
}

func mkStream<A>(p: () -> (A, Ptr<Stream<A>>)?) -> Stream<A> {
    return Stream(project: p)
}

func arrayStream<S:Viewl>(s: S) -> Stream<S.El> {
    if let (x, xs) = s.uncons() {
        return mkStream { (x, Ptr(arrayStream(xs))) }
    } else { return Stream.empty() }
}

func streamN(n: Int) -> Stream<Int> {
    return mkStream {
        return (n, Ptr(streamN(n+1)))
    }
}

func maybe<A,R>(z: R, f: A -> R)(m: A?) -> R {
    if let a = m { return f(a) } else { return z }
}

func viewN<S:Viewl>(n: Int)(s: S) -> [S.El] {
    var res:[S.El] = []
    var s_  = s
    for i in 1..<n {
        if let (a, ss) = s_.uncons() {
            res += a
            s_  = ss
        } else { break }
    }
    return res
}

@tel
Copy link
Author

tel commented Jul 30, 2014

Awesome, thanks!

@tel
Copy link
Author

tel commented Jul 30, 2014

Ultimately made a new revision which fixes up a number of things thanks to the change you proposed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment