Python has them and I find them very useful:
def awesome_fn(x, y):
""""
Calculates some awesome function of x and y.
""""
.
.
.
Then in the iPython REPL you can query it with
In [1]: awesome_fn?
Signature: awesome_fn(x, y)
Docstring: Calculates some awesome function of x and y.
File: ...
Type: function
It's possible to specify documentation for a module using the following documentation format:
module Maybe exposing (Maybe(Just,Nothing), andThen, map, withDefault, oneOf)
{-| This library fills a bunch of important niches in Elm. A `Maybe` can help
you with optional arguments, error handling, and records with optional fields.
# Definition
#docs Maybe
# Common Helpers
#docs map, withDefault, oneOf
# Chaining Maybes
#docs andThen
-}
and for a method:
{-| Convert a list of characters into a String. Can be useful if you
want to create a string primarly by consing, perhaps for decoding
something.
fromList ['e','l','m'] == "elm"
-}
fromList : List Char -> String
fromList = ...
But it's not possible so far to view these docs from repl. There's even an issue related to this.
On the other hand, there's elm-oracle library, which allows you to integrate documentation hints into an editor (and it's already integrated into the popular ones), or even run it in command line as:
elm-oracle FILE query
Related
I'm struggling to understand how exactly modules can be extended in Julia. Specifically, I'd like to create my own LinearAlgebra matrix whose parent class is AbstractMatrix{T} and implement its functionality similar to how the Diagonal or UpperTriangular matrices are implemented in the actual LA package. If I could literally add my matrix to the original package, then I would, but for now I am content creating my own MyLinearAlgebra package that simply imports the original and extends it. Here's what I've got so far in MyLinearAlgebra.jl:
module MyLinearAlgebra
import LinearAlgebra
import Base: getindex, setindex!, size
export
# Types
LocalMatrix,
SolutionVector,
# Functions
issymmetric,
isdiag
# Operators
# Constants
include("SolutionVector.jl")
include("LocalMatrix.jl")
end
Focusing solely on LocalMatrix.jl now, I have:
"""
struct LocalMatrix{T} <: AbstractMatrix{T}
Block diagonal structure for local matrix. `A[:,:,s,iK]` is a block matrix for
state s and element iK
"""
struct LocalMatrix{T} <: AbstractMatrix{T}
data::Array{T,4}
function LocalMatrix{T}(data) where {T}
new{T}(data)
end
end
[... implement size, getindex, setindex! ... all working perfectly]
"""
issymmetric(A::LocalMatrix)
Tests whether a LocalMatrix is symmetric
"""
function issymmetric(A::LocalMatrix)
println("my issymmetric")
all(LinearAlgebra.issymmetric, [#view A.data[:,:,i,j] for i=1:size(A.data,3), j=1:size(A.data,4)])
end
"""
isdiag(A::LocalMatrix)
Tests whether a LocalMatrix is diagonal
"""
function isdiag(A::LocalMatrix)
println("my isdiag")
all(LinearAlgebra.isdiag, [#view A.data[:,:,i,j] for i=1:size(A.data,3), j=1:size(A.data,4)])
end
When I try and run this however, I get
error in method definition: function LinearAlgebra.isdiag must be explicitly imported to be extended
OK not a problem, I can change the definition to function LinearAlgebra.isdiag() instead and it works. But if I also change the definition of the other function to function LinearAlgebra.issymmetric() and run a simple test I now get the error
ERROR: MethodError: no method matching issymmetric(::MyLinearAlgebra.LocalMatrix{Float64})
So I'm stumped. Obviously I have a workaround that lets me continue working for now, but I must be simply misunderstanding how Julia modules work because I can't seem to distinguish between the two functions. Why does one needs to be explicitly extended? Why can the other not? What even is the difference between them in this situation? What is the correct way here to extend a package's module? Thanks for any help.
You need to explicitly state that you are adding new methods to existing functions so it should be:
function LinearAlgebra.issymmetric(A::LocalMatrix)
...
end
function LinearAlgebra.isdiag(A::LocalMatrix)
...
end
The reason that you are getting the error most likely is because you forgot to import LinearAlgebra in the code that is testing your package.
Note that your constructor also should be corrected:
struct LocalMatrix{T} <: AbstractMatrix{T}
data::Array{T,4}
function LocalMatrix(data::Array{T,4}) where {T}
new{T}(data)
end
end
With the current constructor you need to write LocalMatrix{Float64}(some_arr) instead of simply LocalMatrix(some_arr). Even worse, if you provide your constructor with a 3-d array you will get a type conversion error, while when you used the syntax that I am proposing one gets no method matching LocalMatrix(::Array{Int64,3}) which is much more readable for users of your library.
I am trying to abstract inserting objects of different types into sql tables of similar structure. Here's what I'm trying to do:
class TableAccess[A : Meta](table: String) {
def insert(key: String, a: A): ConnectionIO[Unit] = {
(fr"insert into " ++ Fragment.const(table) ++ fr" values ($key, $a);").update.run.map(_ => ())
}
}
But I get this compile error:
[error] diverging implicit expansion for type doobie.util.param.Param[A]
[error] starting with method fromMeta in object Param
[error] (fr"insert into " ++ Fragment.const(table) ++ fr" values ($key, $a);").update.run.map(_ => ())
All I can find in the documentation is:
doobie allows you to interpolate values of any type (and options
thereof) with an Meta instance, which includes...
But it seems that is not enough in this case; what's the right typeclass/imports/conversions I need?
I'll go ahead an answer my own question, almost a year later. I never fully understood what was happening, and I have since updated to a newer version of doobie, so I am not sure how relevant this is. But now the documentation contains this clue:
Note: it is important to understand that Meta exists only to introduce
Get/Put pairs into implicit scope. You should never demand Meta as
evidence in user code: instead demand Get, Put, or both.
def foo[A: Meta](...) // don't do this
def foo[A: Get: Put](...) // ok
And indeed, between that change and the new version, this now compiles just fine for me:
class TableAccess[A: Get: Put](table: String) {
When the compiler is resolving implicit its searches for one of a specific type in the current scope. Here it seems like his finding more than one in his tree search.
It's not a matter of a missing typeclass or imports, it's more like you have too many of them and the compiler cant figure the right one.
Try removing some implicit and see how that works or pass them explicitly.
One way I resolved this was to localize the type parameters (and their evidence) onto the method (on a static/companion object), and then it compiled.
Something like
object MinimalGood {
def good[A: Meta, B: Meta](a: A, b: B): Update0 =
sql"""$a $b""".update
}
http://www.erlang.org/news/35 mentioned that this will be documented, but I can't find it in the documentation.
A "tuple module" is a tuple with two elements, the name of a module and a list of extra arguments. For example:
{my_module, [foo, bar]}
Such a tuple can be used instead of a module name in function calls. In this case, the function being called will get the tuple in question as an additional argument at the end of the argument list:
3> Module = {lists, [[foo]]}.
{lists,[[foo]]}
4> Module:append([bar]).
[bar|{lists,[[foo]]}]
This call is equivalent to:
7> lists:append([bar], {lists, [[foo]]}).
[bar|{lists,[[foo]]}]
Tuple modules are kept for backwards compatibility, as they were the implementation mechanism for parameterised modules, which were removed from the language in R16.
I'm completely new to CL, and I'd like to learn how to read documentation strings and get other help information from the REPL. Something like help(symbol) in Python, or symbol? in iPython, or :t and :i in Haskell's GHCi.
So, given a symbol name, I'd like to be able to know:
what kind of value it is bound to, if any (a function, a variable, none at all)
if it is a function or a macro, then what are its positional arguments
if it has a docstring, show it
what package or file it is coming from or when it was defined
I found there is (documentation '_symbol_ '_type_), but it is not exactly what I need. I need to know the type of value the symbol is bound to ('function, 'variable, 'compiler-macro, etc.) before I can use documentation. Then it returns only the docstring, it may be missing or not sufficient to use the symbol.
For example, in Lisp, the help for mapcar is not very useful (CLisp's REPL):
> (documentation 'mapcar 'function)
NIL
I'd like to be able to see something like this instead:
>>> map?
Type: builtin_function_or_method
Base Class: <type 'builtin_function_or_method'>
String Form: <built-in function map>
Namespace: Python builtin
Docstring:
map(function, sequence[, sequence, ...]) -> list
Return a list of the results of applying the function to the items of
the argument sequence(s). If more than one sequence is given, the
function is called with an argument list consisting of the corresponding
item of each sequence, substituting None for missing values when not all
sequences have the same length. If the function is None, return a list of
the items of the sequence (or a list of tuples if more than one sequence).
As mentioned Common Lisp has standard functions: DESCRIBE, INSPECT and DOCUMENTATION. Typical Lisp IDEs also have these bound to keys and menus.
For standard Common Lisp functionality most IDEs directly link to the Common Lisp HyperSpec documentation with a keystroke.
Most IDEs also have keystrokes to show the arglist and the documentation. There is also the 'arglist on space' functionality.
LispWorks specific examples: LispWorks Argument list information and LispWorks Expressions menu
I can recommend to read the IDE manual for Slime, LispWorks Editor, Allegro CL's ELI, or whatever IDE you are using.
Regarding your question about getting the type of symbol: there is no such thing. Or, more precisely, symbols are not just names of other objects, but themselves objects of the type SYMBOL. Each symbol can have both a variable value and a function value. To check if it has a variable value, use BOUNDP, and to check for a function value FBOUNDP.
In my application I need to serialize a vector containing an arbitrary datatype, in this case is a list of Doubles. For serializing the vector I'm importing Data.Vector.Binary.
When loading the module in GHCi the following error arises:
Overlapping instances for Binary [Double]
arising from a use of `decode' at Statistics.hs:57:33-42
Matching instances:
instance (Data.Vector.Generic.Base.Vector v a, Binary a) =>
Binary (v a)
-- Defined in Data.Vector.Binary
instance (Binary a) => Binary [a] -- Defined in Data.Binary
Is the list an instance of Vector?
I looked through the documentation but could not find such instance.
What can I do to be able to serialize this structure?
Edit:
I'm using the following package versions:
vector-0.6.0.2
vector-binary-instances-0.1.2
binary-0.5.0.2
Also here is a snippet that shows the issue, this time with a list of chars:
import Data.Binary
import Data.Vector.Binary
import qualified Data.ByteString.Lazy as L
main = L.writeFile "/tmp/aaa" $ encode "hello"
Ok, I think I see the problem here. The vector-binary-instances package defines:
instance (Data.Vector.Generic.Base.Vector v a, Binary a) => Binary (v a)
which is very bad. This definition means "for any type 'v a', this is a valid Binary instance". That means this instance is available for any type that matches v a. That includes (but is not limited to) all lists, all functors, and all monads. As a demonstration, ghci reports the following:
Prelude Data.Binary Data.Vector.Binary Data.ByteString.Lazy> :t getChar
getChar :: IO Char
Prelude Data.Binary Data.Vector.Binary Data.ByteString.Lazy> encode getChar
<interactive>:1:0:
No instance for (Data.Vector.Generic.Base.Vector IO Char)
arising from a use of `encode' at <interactive>:1:0-13
Possible fix:
add an instance declaration for
(Data.Vector.Generic.Base.Vector IO Char)
In the expression: encode getChar
In the definition of `it': it = encode getChar
Here the interpreter is attempting to use this instance for getChar :: IO Char, which is obviously wrong.
Short answer: don't use vector-binary-instances for now. This instance is broken, and given how instances propagate through Haskell code it will cause problems. Until this is fixed, you should write your own binary instances for vectors. You should be able to copy the code from vector-binary-instances and restrict it to a monomorphic vector type
instance (Binary a) => Binary (Vector a) where
I believe this will work with any Vector which is an instance of Data.Vector.Generic.Vector.
You also may want to contact the vector-binary-instances maintainer about this.