kotovalexarian / typeclass.rb Goto Github PK
View Code? Open in Web Editor NEWHaskell type classes in Ruby.
License: MIT License
Haskell type classes in Ruby.
License: MIT License
The only possibility to use lexical scope in Ruby is refinements.
Refinements can be created dynamically:
def foo(m)
Module.new do
refine m.singleton_class do
define_method :foo do
12345
end
end
end
end
module Foo
end
module Bar
using foo Foo
def self.bar
Foo.foo
end
end
Bar.bar #=> 12345
This can be used to create instance of typeclass:
Foo = Typeclass.new :a do
fn :foo, [:a]
end
module Bar
using Foo.instance Integer do
def foo(n)
n + 1
end
end
def self.bar(n)
Foo.foo(n)
end
end
Bar.bar(1) #=> 2
Foo.foo(1) # raises exception
The problem is that we can't see other instances of typeclass in Typeclass#instance
method because it is out of the lexical scope where refine is used.
One idea is to return Typeclass.instance
syntax (which was removed in #23) and use refinements for object Typeclass
:
Foo = Typeclass.new :a do
fn :foo, [:a]
end
module Bar
using Typeclass.scope
Typeclass.instance Foo, Integer do
# ...
end
end
Also refinements can be used for typeclass' instance in the same way but without return to the old syntax:
Foo = Typeclass.new :a do
fn :foo, [:a]
end
module Bar
using Foo.scope
Foo.instance Integer do
# ...
end
end
To support infix functions (#25) using
should be called with instance:
Foo = Typeclass.new :a do
infix :foo, [:a, :a]
end
using Foo.instance Integer do
def foo(this, other)
this + other
end
end
2.foo(3) #=> 5
Constraints of type variables other than Object
are used rarely. Keys are confusing because they don't imply order. Positional type parameters are used at least in definition of superclass (include Foo[:a, :b]
). Also they maybe will be used in instance definition (#16). The positional syntax is closer to Haskell. Optional hash may be used to specify constraint.
Now:
Foo = Typeclass.new a: Object, b: Object do
# ...
end
Bar = Typeclass.new a: Object, b: Comparable, c: Object do
include Foo[:c, :b]
# ...
Want:
Foo = Typeclass.new :a, :b do
# ...
end
Bar = Typeclass.new :a, :b, :c, { b: Comparable } do
# ...
Foo = Typeclass.new :a do
infix :foo, [:a, :a]
end
Foo.instance Integer do
def foo(this, other)
this + other
end
end
2.foo(3) #=> 5
Monad = Typeclass.new :m do
fn bind: -> { m[a] ** (a ** m[a]) ** m[b] }
fn ret: -> { a ** m[a] }
end
Monad = Typeclass.new :m do
fn bind: 'm a -> (a -> m a) -> m b'
fn ret: 'a -> m a'
end
module Foo
BAR = 123
def self.bar(&block)
block.binding.eval 'BAR'
end
end
BAR = 456
Foo.bar {} #=> 456
Don't specify type parameter keys. Match type parameters by positions instead.
Now:
Typeclass.instance Foo, a: Integer do
# ...
Want:
Typeclass.instance Foo, Integer do
# ...
This code can behave differently in cases if it was optimized or not. Typeclass can be frozen, so we can make assumptions about it's functions. The problem concerns to infix functions.
Foo = Typeclass.new :a do
infix :foo, [:a]
end
class A
end
Foo.instance A do
def foo(this)
foo this # some recursion
end
end
class B < A
def foo
fail # some unexpected behavior
end
end
http://www.sitepoint.com/rubys-important-hook-methods/
http://stackoverflow.com/questions/708642/how-to-make-a-base-class-method-non-overridable-in-ruby
http://scie.nti.st/2008/9/17/making-methods-immutable-in-ruby/
http://stackoverflow.com/questions/2441524/closest-ruby-representation-of-a-private-static-final-and-public-static-final
https://www.ruby-forum.com/topic/65458
Remove:
Typeclass.instance Foo, Integer do
# ...
Keep:
Foo.instance Integer do
# ...
Allow subclasses to redefine functions.
Eq = Typeclass.new a: Object do
fn :eq, [:a, :a]
fn :ne, [:a, :a] do |a1, a2|
!eq(a1, a2)
end
end
Ord = Typeclass.new Eq[:a], a: Object do
fn :cmp, [:a, :a]
fn :eq, [:a, :a] do |a1, a2|
cmp(a1, a2).zero?
end
fn :lt, [:a, :a] do |a1, a2|
cmp(a1, a2) < 0
end
fn :le, [:a, :a] do |a1, a2|
cmp(a1, a2) <= 0
end
fn :gt, [:a, :a] do |a1, a2|
cmp(a1, a2) > 0
end
fn :ge, [:a, :a] do |a1, a2|
cmp(a1, a2) >= 0
end
end
MyType = Struct.new :n
Typeclass.instance Eq, a: MyType do
end
Typeclass.instance Ord, a: MyType do
def cmp(a1, a2)
a1.n <=> a2.n
end
end
Ord.eq MyType.new(1), MyType.new(1) #=> true
Ord.ne MyType.new(1), MyType.new(2) #=> true
Ord.gt MyType.new(2), MyType.new(1) #=> true
Ord.ge MyType.new(2), MyType.new(2) #=> true
A 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.