I am playing around with making a Fibonacci Heap. (They are mentioned several times in an algorithms class that I'm taking, and I want to check them out.) I want the heap to use nodes of any kind, so I define a Node interface:
package node
type Node interface {
AddChild(other Node)
Less(other Node) bool
}
type NodeList []Node
func (n NodeList) AddNode(a Node) {
n = append(n, a)
}
(I use the []Node array because it has the same affect as the heap definition.) As you can see, the Node interface defines its two functions with arguments of type Node. This should mean that the functions have to accept arguments that implement the Node interface. The rest of the heap uses these nodes.
In the program that uses this heap, I make a type that implements the Node interface:
package main
import "container/list"
import node "./node"
type Element struct {
Children *list.List
Value int
}
func (e Element) AddChild(f Element) {
e.Children.PushBack(f)
}
func (e Element) Less(f Element) bool {
return e.Value < f.Value
}
func main() {
a := Element{list.New(), 1}
n := new(node.NodeList)
n.AddNode(a)
}
However, this didn't work. The compiler complains that Element doesn't have the correct function definitions for the interface.
cannot use a (type Element) as type node.Node in function argument:
Element does not implement node.Node (wrong type for AddChild method)
have AddChild(Element)
want AddChild(node.Node)
What is wrong here? Obviously Element doesn't implement the interface correctly, but I think it's because of how I defined the interface. Is there a correct way to do what I want in Go? Can interfaces refer to themselves?
The function
func (e Element) Less(f Element) bool
does not match the function from the interface
func Less(other Node) bool
You need to actually match the signature, as in
func (e Element) Less(f Node) bool
And yes, this means you could be passed a Node that isn't an Element. You'll have to test for that at runtime and panic.
As an example for why this is so, consider if your code was legit, and I tried the following:
type Other int
func (o Other) Less(f Other) bool {
return o < f
}
func (o Other) AddChild(f Other) {}
e = GetSomeElement() // of type Element
var o Other
var n Node = e
fmt.Println(n.Less(o))
Because I stored the Element into a var of type Node, I can now call Less() with an argument that isn't another Element, which violates the type of Element.Less(). This is why that's not legal.
Related
Reading Swift Programming Language book I've seen number of references to type Element, which is used to define type of collection items. However, I can't find any documentation on it, is it class, protocol? What kind of functionality/methods/properties it has?
struct Stack<Element>: Container {
// original Stack<Element> implementation
var items = [Element]()
mutating func push(_ item: Element) {
items.append(item)
}
...
If we tried trace the idea of how we do even get Element when working with collections, we would notice that it is related to the Iterator protocol. Let's make it more clear:
Swift Collection types (Array, Dictionary and Set) are all conforms to Collection protocol. Therefore, when it comes to the Collection protocol, we can see that the root of it is the Sequence protocol:
A type that provides sequential, iterated access to its elements.
Sequence has an Element and Iterator associated types, declared as:
associatedtype Element
associatedtype Iterator : IteratorProtocol where Iterator.Element == Element
You could review it on the Sequence source code.
As shown, Iterator also has an Element associated type, which is compared with the sequence Element, well what does that means?
IteratorProtocol is the one which does the actual work:
The IteratorProtocol protocol is tightly linked with the Sequence
protocol. Sequences provide access to their elements by creating an
iterator, which keeps track of its iteration process and returns one
element at a time as it advances through the sequence.
So, Element would be the type of returned element to the sequence.
Coding:
To make it simple to be understandable, you could implement such a code for simulating the case:
protocol MyProtocol {
associatedtype MyElement
}
extension MyProtocol where MyElement == String {
func sayHello() {
print("Hello")
}
}
struct MyStruct: MyProtocol {
typealias MyElement = String
}
MyStruct().sayHello()
Note that -as shown above- implementing an extension to MyProtocol makes MyElement associated type to be sensible for the where-clause.
Therefore sayHello() method would be only available for MyProtocol types (MyStruct in our case) that assign String to MyElement, means that if MyStruct has been implemented as:
struct MyStruct: MyProtocol {
typealias MyElement = Int
}
you would be not able to:
MyStruct().sayHello()
You should see a compile-time error:
'MyStruct.MyElement' (aka 'Int') is not convertible to 'String'
The same logic when it comes to Swift collection types:
extension Array where Element == String {
func sayHello() {
print("Hello")
}
}
Here is the definition in the Apple documentation
Element defines a placeholder name for a type to be provided later.
This future type can be referred to as Element anywhere within the
structure’s definition.
Element is usually used as the generic type name for collections, as in
public struct Array<Element> { ... }
so it is what you construct your array from, and not something predefined by the language.
Element is a purpose-built (and defined) placeholder for structures. Unlike some of the answers/comments have suggested, Element cannot always be substituted for T because T without the proper context is undefined. For example, the following would not compile:
infix operator ++
extension Array {
static func ++ (left: Array<T>, right: T) -> Array {
...
}
}
The compiler doesn't know what T is, it's just an arbitrary letter—it could be any letter, or even symbol (T has just become Swift convention). However, this will compile:
infix operator ++
extension Array {
static func ++ (left: Array<Element>, right: Element) -> Array {
...
}
}
And it compiles because the compiler knows what Element is, a defined placeholder, not a type that was arbitrarily made up.
I bumped into this example of a cool Swift technique without an explanation of how it works or what it does, and even though I've written a decent amount of Swift code, this is so full of intricate Swiftisms it's currently twisting my head around.
If there's someone proficient enough with Swift who doesn't mind dissecting it and discerning its purpose, it would really increase my grasp of the language and its more powerful features, and probably enlighten others as well.
extension Array {
var match : (head: T, tail: [T])? {
return (count > 0) ? (self[0], Array(self[1..<count])) : nil
}
}
func map<A, B>(f: A -> B, arr: [A]) -> [B] {
if let (head, tail) = arr.match {
return [f(head)] + map(f, tail)
} else {
return []
}
}
The extension to the Array type defines a new computed property called match. This property is of type (head: T, tail: [T])?, so an optional tuple where the first element (named head) is of type T and the second element (named tail) is of type Array of T. T is just the generic type for the type of the element that is stored inside of the array (Since Array is a generic collection itself).
var match : (head: T, tail: [T])? {
return (count > 0) ? (self[0], Array(self[1..<count])) : nil
}
This computed property either returns nil, if the Array doesn't contain any elements, or it returns a tuple containing the first element of the list (self[0] and the tail of the list (everything except for the first element): Array(self[1..<count]).
Now that array have this computed property we can make use of it to recursively call a function f on the elements of an array and return a new Array that contains the results of those function calls. This is what a map function does:
func map<A, B>(f: A -> B, arr: [A]) -> [B] {
if let (head, tail) = arr.match {
return [f(head)] + map(f, tail)
} else {
return []
}
}
The mapping function f is of type A -> B which means that it maps elements of type A to elements of type B, therefore map has to be passed an array of type [A]. Then, using the match variable and optional binding we can call f on the head of the list [f(head)] and put it inside of a new list and then append the result of the recursive map call for the rest of the array elements map(f, tail).
To understand the map function they're trying to implement better:
I'm trying to reach this way of polymorphism in GO
type Discoverer interface {
Discover() string
}
type A struct {
}
func (obj A) GetTest() string {
return "im in A"
}
type B struct {
A
}
func (obj B) GetTest() string {
return "im in B"
}
func (obj A) Discover() string {
return obj.GetTest()
}
func main() {
a := A{}
b := B{}
fmt.Println(a.Discover())
fmt.Println(b.Discover())
}
Now I'm getting in output
im in A
im in A
So, my question is: It is possible to see in output
im in A
im in B
Without "override" Discover of B?
func (obj B) Discover() string {
return obj.GetTest()
}
Why? I've alot of small methods in struct (as classes) and Discover pretty the same for all structs, so I want to avoid copy&paste Discover in each struct(class)
go playground https://play.golang.org/p/nYc2hc3UbG
Thanks in advance!
No. You're embedding A in B. B has no definition for Discover, therefor the version on A is always invoked. That method has a receiver of type A and A has no awareness of B or the fact that it's embedded in B. Therefor A can only call it's own version of GetTest().
The only reason B satisfies the discover interface is because it has A embedded. It implements it indirectly. If you want the functionality on B, you have to define it on B. This isn't polymorphism at all, it's composition. B isn't an A, B has an A. If you want polymorphism, you use interfaces and implement them. B is a discoverable, but only because it has an A.
I would assume this is just for the example but you actually have no reason at all to even have this Discovery method. Your interface should just require GetTest instead. Don't confuse embedding with inheritance. There is no inheritance in Go. If you want polymorphic behavior you achieve it by implementing interfaces and you can't cut corners like this because the relationship between an embedded type and the embeddor is not one of inheritance, there is no base class or "overrides".
To add to #evanmcdonnal's point, embedding is neither inheritance nor polymorphism. Inheritance just happens to be a convenience such that you may get the implementation of an interface for free but in Go, its explicit. Embedding may seem like inheritance but is not, as #evanmcdonnal has pointed out.
Rather, you should separate the concepts polymorphism from inheritance and embedding and inheritance. The comparisons do not carry over from most object oriented languages. As an example, below would be an implementation of polymorphism. Notice that Discover takes an interface and A and B implements the interface, making the function itself polymorphic.
package main
import "fmt"
type A struct{}
type B struct{}
type Test interface{
GetTest() string
}
func (a *A) GetTest() string {
return "i am in A"
}
func (b *B) GetTest() string {
return "i am in B"
}
func Discover(t Test) string {
return t.GetTest()
}
func main() {
a := &A{}
b := &B{}
fmt.Println(Discover(a))
fmt.Println(Discover(b))
}
I have the following (simple) data structure:
struct Work<Input, Output> {
let work: Input -> Output
}
This type represents work which can take an Input and turns in into a desired Output. I am trying to see whether this data structure conforms to some functional concepts like a functor or a monad.
Functor
extension Work {
func map<MoreOutput>(transform: Output -> MoreOutput) -> Work<Input, MoreOutput> {
return Work<Input, MoreOutput> {
return transform(self.work($0))
}
}
}
That seems to be correct as far as I am aware. I am able to write a map function which can turn Work<Input, Output> into Work<Input, MoreOutput>
Monad
I have trouble thinking of the definition for a flatMap (or fold) function for Work. The only thing I can come up with is the following:
extension Work {
func flatMap<MoreOutput>(transform: Work<Output, MoreOutput>) -> Work<Input, MoreOutput> {
return Work<Input, MoreOutput> { input in
return transform.work(self.work(input))
}
}
}
If you look up the flatMap definition for an Array in swift it looks like this (simplified):
func flatMap(transform: (Element) -> T?) -> [T]
This is a function where its argument is a function which transforms an Element into T and results an Array. I cannot think of a way to abstract this to the Work type.
From another functional book I found a general definition for flatMap as follows (on an object F holding type A):
func flatMap<B>(f: A -> F<B>) -> F<B>
which is a different definition of flatMap than Array seems to implement.
Can someone explain this difference to me? And is it even possible to define a 'correct' flatMap function on Work? Or does Work not satisfy the properties to be a Monad?
** Edit
Thanks phg for so much useful info. I've tried to do the Profunctor definition:
Making Work a Profunctor:
extension Work {
func diMap<A, B>(fa: A -> Input, fb: Output -> B) -> Work<A, B> {
return Work<A, B> { arg in
let input = fa(arg)
let output = self.work(input)
return fb(output)
}
}
}
Does that look right to you?
This:
func flatMap<B>(f: A -> F<B>) -> F<B>
is what you want flatMap to look like; it's the monad's usual "bind" operation. Specialized for functions over the second argument, you get the so-called Reader monad:
extension Work {
func flatMap<MoreOutput>(g: Output -> Work<Input, MoreOutput>) -> Work<Input, MoreOutput> {
// (Reader f) >>= g = Reader $ \x -> runReader (g (f x)) x
return Work<Input, MoreOutput> {
g(self.work($0)).work($0)
}
}
}
Note: I actually don't speak Swift, this code was just guessing -- hence the included Haskell original. Feel free to edit in a corrected version.
Now to the other definition:
func flatMap(transform: (Element) -> T?) -> [T]
I suppose T? means something like "optional T" or "nullable T". This is not what we usually understand as a monadic function, but it is related. Indeed, there has been a question about such "generalized flatMaps". The answer is, that if two monads are compatible, i.e., there exists a monad morphism F<A> -> G<A> preserving monadic structure, it makes sense to define
func wrappedFlatMap<B>(f: A -> F<B>) -> G<B>
which is probably exactly what is happening here for the "option type" and the list type, where the morphism is logically just
Just x ~> [x]
Nothing ~> []
I have generic and I want to be able to initialize it with specific constrains. The constraints are only there for initialization. The rest of the class doesn't care. Here is a simplified example:
struct Generic<T> {
let compare: (T, T) -> Bool
init<T: Equatable>(data: [T]) {
let handler: (T, T) -> Bool = { $0 == $1 }
compare = handler
insert(data)
}
init(compareHandler: (T, T) -> Bool, data[T]) {
compare = self.compareHandler
insert(data)
}
}
You can see there's two initializers. The second one obviously works fine. However, in the first one the local type T is mismatched with the struct's generic Type. So, for example, attempting to insert data I get Cannot invoke 'insert' with an argument list of type '([T])'. Is it possible for me to specialize the Struct's generic type only for the initialization or a specific function?
Note, I've already tried init<T where T:Equatable>(data: [T]) to the same effect.
Update
I'm using the following workaround: I create a top level function and removing the specialized init:
func equatableHandler<T: Equatable>(left: T, right: T) -> Bool {
return left == right
}
Clients of the struct can initialize using: Generic(compareHandler: equatableHandler, data: data)
It's not quite the "convenience" of using a specialized init, but I suppose it works well enough for my purposes. I'm not a fan of creating top-level functions, but the generic is used so often for "Equatable" generics that it makes sense for me to define the handler once for clients to use.
The problem is that the first init method
init<T: Equatable>(data: [T])
introduces a local type placeholder T which hides (and is completely
unrelated to) the placeholder T of the Generic type, so it
is essentially the same problem as in Array extension to remove object by value.
As of Swift 2 you can solve that with a "restricted extension":
extension Generic where T : Equatable {
init(data: [T]) {
let handler: (T, T) -> Bool = { $0 == $1 }
compare = handler
// ...
}
}
For Swift 1.x the only solution is probably to define a global helper
function
func makeGeneric<T : Equatable>(data: [T]) -> Generic<T> {
return Generic(compareHandler: { $0 == $1 }, data: data)
}
(and I could not think of a sensible name for the function :).