Skip to content

Instantly share code, notes, and snippets.

@jcmoyer
Last active March 31, 2023 04:02
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jcmoyer/5632949 to your computer and use it in GitHub Desktop.
Save jcmoyer/5632949 to your computer and use it in GitHub Desktop.
-- implements an option type as a tagged union
local option = {}
local mt = { __index = option }
local function isoption(t)
return getmetatable(t) == mt
end
function option.some(a)
local instance = {
tag = 'some',
value = a
}
return setmetatable(instance, mt)
end
function option.none()
local instance = {
tag = 'none'
}
return setmetatable(instance, mt)
end
function option.type(x)
if x:issome() or x:isnone() then
return x.tag
else
-- incorrect metatable or invalid tag field
return nil
end
end
-- bind :: 'a option -> ('a -> 'b option) -> 'b option
function option:bind(f)
assert(isoption(self), 'not an option')
if self:issome() then
return f(self.value)
else
return option.none()
end
end
-- map :: 'a option -> ('a -> 'b) -> 'b option
function option:map(f)
assert(isoption(self), 'not an option')
if self:issome() then
return option.some(f(self.value))
else
return option.none()
end
end
-- mutate :: 'a option -> ('a -> 'b) -> ()
function option:mutate(f)
assert(isoption(self), 'not an option')
if self:issome() then
self.value = f(self.value)
end
end
-- get :: 'a option -> 'a
function option:get()
assert(isoption(self), 'not an option')
assert(self:issome(), 'option is none')
return self.value
end
-- isnone :: 'a option -> bool
function option:isnone()
return isoption(self) and self.tag == 'none'
end
-- issome :: 'a option -> bool
function option:issome()
return isoption(self) and self.tag == 'some'
end
return option
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment