How to specialize a generic enum in Swift - swift

I'm using the antitypical/result package to provide a generic Result type. This package defines Result as follows:
public enum Result<T, Error> {
...
}
Now, I only wish to return errors of type NSError in my code, so it would be nice if I didn't have to keep doing things this:
func myFunc() -> Result<String, NSError> { ... }
Instead, I want to create a derived StdResult type so that I can do this instead:
func myFunc() -> StdResult<String> { ... }
I've tried various things but I can't find a solution. This, for example, doesn't work:
typealias StdResult<T> = Result<T, NSError>
Is there a solution which will work?

Unfortunately we're pretty limited here. Swift doesn't support generic typealias, so we can do this as a sort of hack with struct:
struct StdResult<T> {
typealias Type = Test<T, NSError>
}
func myFunc() -> StdResult<String>.Type {
}
Does that fit what you were looking for closely enough?

At the moment, there's no generic typealias support nor enumeration inheritance, but you could use RawRepresentable protocol. It's not as easy as if a generic typealias exists, but it may fit your needs.
RawRepresentable
From Apple's documentation:
A type that can be converted to an associated "raw" type, then converted back to produce an instance equivalent to the original.
public protocol RawRepresentable {
typealias RawValue
public init?(rawValue: Self.RawValue)
public var rawValue: Self.RawValue { get }
}
That said, your raw value must be Result<T, NSError>:
enum StdResult<T>: RawRepresentable {
var rawValue: Result<T, NSError> {
switch self {
case .Success(let value):
return Result.Success(value)
case .Failure(let error):
return Result.Failure(error)
}
}
init?(rawValue: Result<T, NSError>) {
switch rawValue {
case .Success(let value):
self = .Success(value)
case .Failure(let error):
self = .Failure(error)
}
}
case Success(T)
case Failure(NSError)
}
func myFunc() -> StdResult<String> { }
Note: Properties and methods of original Result enumeration are only accessible from rawValue property, so, for example, if you want to compare your new StdResult with another, you must use rawValue property or reimplement these protocols yourself.

You could alias the specific Result type so you don't have to constantly do func myThing() -> Result<String, NSError>
e.g.
typealias StringResult = Result<String, NSError>
func myOtherThing() -> StringResult
It's more difficult for me to come up with a generic solution like
MyResult<String>
without understanding exactly what Result is doing. I could take another crack at it if you post some of the internals.

Related

Enum to map to a comparable key path

I'm writing some code where a user can select how a particular array of data is sorted. I was trying to see if I could hold the set of permissible sort properties in an enum. What I want to be able to express is something like:
import Foundation
struct MyStruct {
let a: Int
let b: Int
}
enum MyStructProps {
case a, b
func comparableKeyPath<T: Comparable>() -> KeyPath<MyStruct, T> {
switch self {
case .a: return \MyStruct.a
case .b: return \MyStruct.b
}
}
}
At the moment each case returns a compiler error: key path value type 'Int' cannot be converted to contextual type 'T'.
Looking at the post Swift Generics, Constraints, and KeyPaths I would need to embed this within a sort function, so that Swift knows how to derive the type of the generic key path.
But I was curious to learn if there is a way of returning a generic keypath in my naive code?
If you need to work at some more intermediate level than the following, you'll need to type-erase, as Sweeper says in the comment.
Otherwise, because you can't return different types from one function, just employ generics for the intermediate steps, and have one function at the end of the process that employs multiple types.
extension Sequence where Element == MyStruct {
func sorted(by property: Element.ComparableProperty) -> [Element] {
switch property {
case .a: return sorted(by: \.a)
case .b: return sorted(by: \.b)
}
}
}
extension MyStruct {
enum ComparableProperty {
case a, b
}
}
public extension Sequence {
/// Sorted by a common `Comparable` value.
func sorted<Comparable: Swift.Comparable>(
by comparable: (Element) throws -> Comparable
) rethrows -> [Element] {
try sorted(by: comparable, <)
}
/// Sorted by a common `Comparable` value, and sorting closure.
func sorted<Comparable: Swift.Comparable>(
by comparable: (Element) throws -> Comparable,
_ areInIncreasingOrder: (Comparable, Comparable) throws -> Bool
) rethrows -> [Element] {
try sorted {
try areInIncreasingOrder(comparable($0), comparable($1))
}
}
}

Can a Swift enum have a function/closure as a raw value?

I know an enum can have a closure as an associated value, such as:
enum SomeEnum {
case closureOne (String, Double -> Double)
case closureTwo (String, (Double, Double) -> Double)
}
But, can an enum have a closure as a raw value? For instance, does something like this work?
enum someEnum: () -> Void {
case closureOne = doSomething
case closureTwo = doSomethingElse
}
where
let doSomething = {
// Do something here.
}
let doSomethingElse {
// Do something else here.
}
It's not as straight forward, but you could use OptionSet, see this page:
Unlike enumerations, option sets provide a nonfailable init(rawValue:) initializer to convert from a raw value, because option sets don’t have an enumerated list of all possible cases. Option set values have a one-to-one correspondence with their associated raw values.
Could be something like this:
func doSomething() {}
func doSomethingElse() {}
struct MyClosures: OptionSet {
static let closureOne = MyClosures(rawValue: doSomething)
static let closureTwo = MyClosures(rawValue: doSomethingElse)
let rawValue: () -> Void
init(rawValue: #escaping () -> Void) {
self.rawValue = rawValue
}
init() {
rawValue = {}
}
mutating func formUnion(_ other: __owned MyClosures) {
// whatever makes sense for your case
}
mutating func formIntersection(_ other: MyClosures) {
// whatever makes sense for your case
}
mutating func formSymmetricDifference(_ other: __owned MyClosures) {
// whatever makes sense for your case
}
static func == (lhs: MyClosures, rhs: MyClosures) -> Bool {
// whatever makes sense for your case
return false
}
}
And so you can use it as:
let myClosures: MyClosures = [ .closureOne, .closureTwo ]
HOWEVER looking at your explanation in the comment:
So I'm trying to find the most efficient way to run a function given the state of a variable.
I think what you actually want is some sort of state machine. Some examples are available here and here

How can I create a function in Swift that returns a Type which conforms to a protocol?

How can I create a function in Swift that returns a Type which conforms to a protocol?
Here is what I'm trying right now, but it obviously won't compile like this.
struct RoutingAction {
enum RoutingActionType{
case unknown(info: String)
case requestJoinGame(gameName: String)
case requestCreateGame(gameName: String)
case responseJoinGame
case responseCreateGame
}
// Any.Type is the type I want to return, but I want to specify that it will conform to MyProtocol
func targetType() throws -> Any.Type:MyProtocol {
switch self.actionType {
case .responseCreateGame:
return ResponseCreateGame.self
case .responseJoinGame:
return ResponseJoinGame.self
default:
throw RoutingError.unhandledRoutingAction(routingActionName:String(describing: self))
}
}
}
I would personally prefer returning an instance instead of a type but you can do it that way too. Here's one way to achieve it:
protocol MyProtocol:class
{
init()
}
class ResponseCreateGame:MyProtocol
{
required init() {}
}
class ResponseJoinGame:MyProtocol
{
required init() {}
}
enum RoutingActionType
{
case unknown(info: String),
requestJoinGame(gameName: String),
requestCreateGame(gameName: String),
responseJoinGame,
responseCreateGame
// Any.Type is the type I want to return, but I want to specify that it will conform to MyProtocol
var targetType : MyProtocol.Type
{
switch self
{
case .responseCreateGame:
return ResponseCreateGame.self as MyProtocol.Type
case .responseJoinGame:
return ResponseJoinGame.self as MyProtocol.Type
default:
return ResponseJoinGame.self as MyProtocol.Type
}
}
}
let join = RoutingActionType.responseJoinGame
let objectType = join.targetType
let object = objectType.init()
Note that your protocol will need to impose a required init() to allow creation of instances using the returned type.
Note2: I changed the structure a little to make my test easier but i'm sure you'll be able to adapt this sample to your needs.
Why do you not want to use simple:
func targetType() throws -> MyProtocol
?
EDIT:
I think you can't. Because if you return Type actually you return an instance of class Class and it can't conform your protocol. This runtime's feature was inherited from objective-c. You can see SwiftObject class.

How to check if an instance is of type enum

'emun' seems to me like a keyword or a primitive type.
And obviously following code does not compile:
if self is enum {
}
But how can I be able to check if certain protocol is implemented by any enum?
protocol Enumatable {
}
extension Enumatable {
func isEnum() -> Bool {
return self is enum //it does not compile
}
}
But what I really want is to set some kind of constraint in the protocol to force the adopting class to be an enum. Is that possible?
Thanks!
I'm not sure how performant it is to use Mirrors. But here you go:
enum SomeEnum {
case one
case two
}
let mirror = Mirror(reflecting: SomeEnum.one)
if let displayStyle = mirror.displayStyle {
switch displayStyle {
case .enum:
print("I am an enum")
default:
print("not an enum")
}
}

Implement an Equatable Void (None) type

I am implementing result objects using Result, it defines a boxed result like an Optional with an enum:
public enum Result<T, Error>: Printable, DebugPrintable {
case Success(Box<T>)
case Failure(Box<Error>)
...
}
The Equatable protocol defined for Result is as follows:
public func == <T: Equatable, Error: Equatable> (left: Result<T, Error>, right: Result<T, Error>) -> Bool
So, T must conform Equatable.
I would like to be able to have a Success that boxes a Void alike type. But, Void is not Equatable as it's defined as an empty tuple:
typealias Void = ()
The purpose is to be able to have Result types where I do not care about the a value when succeeds.
Is it possible to have an Equatable Void (or no value)?
As quick thoughts, there's the possibility to create an empty struct, but I am looking (if possible) for a more elegant solution.
Why not make Success contain an Optional? (Box<T?> or Box<t>?)?
The you could return nil. The downside is you would be left unwrapping your result
Trying again in Swift 2.0, it seems that Void can be initialized as Void():
public enum Result<T, Error: ErrorType> {
case Success(T)
case Failure(Error)
var value: T? {
switch self {
case .Success(let v):
return v
case .Failure(_):
return nil
}
}
/// Constructs a success wrapping a `value`.
public init(value: T) {
self = .Success(value)
}
/// Constructs a failure wrapping an `error`.
public init(error: Error) {
self = .Failure(error)
}
}
enum MyError: ErrorType {
case AnError
}
let result = Result<Void, MyError>(value: Void())
let success = result.value != nil // returns true
let error = result.value == nil // returns false
My solution to this issue is as you suggest to make a new struct that contains no members. I'll post it here for others who need a working solution.
Make it Decodable and Equatable. Now you can treat "Void" like a real type. You can just map to this value wherever you need it or map back out.
typealias VoidDecodableResult = ((Result<VoidDecodable, Error>) -> Void)
struct VoidDecodable: Decodable, Equatable {}
One thing is in your success block in a generic function you can just try to cast to VoidDecodable and return an instance.
if T.self is VoidDecodable.Type {
completion(.success(VoidDecodable() as! T))
return
}
Add a helper to make mapping out easier:
struct VoidDecodable: Decodable, Equatable {
var orVoid: Void {
()
}
}