# Searching for functions

**URL:** <https://discuss.ocaml.org/t/searching-for-functions/3698>\
**Category:** Learning\
**Tags:** documentation\
**Created:** [April 22, 2019, 7:25pm UTC](https://discuss.ocaml.org/t/searching-for-functions/3698 "2019-04-22T19:25:51Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![jmackie](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/jmackie/32/1548_2.png) [@jmackie](https://discuss.ocaml.org/u/jmackie)\
**Post date:** [April 22, 2019, 7:25pm UTC](https://discuss.ocaml.org/t/searching-for-functions/3698/1 "2019-04-22T19:25:51Z")

</div>

OCaml newbie here - coming from Haskell land out of curiosity.

I’m interested how you guys find your way around stdlib/packages etc?

Example: I’m writing a script and I want to lookup an environment variable. I know there’s probably some function along the lines of `get_env` somewhere, so I’d like to know where it is and what type it has. In Haskell I’d do a hoogle search along the lines of [https://www.stackage.org/lts-13.18/hoogle?q=getenv](https://www.stackage.org/lts-13.18/hoogle?q=getenv) - what would be my process in OCaml?

I tried googling “get env var in Ocaml” - first hit is a link to stdlib, but I’m using base. It did at least give me the hint that `Sys` is a relevant namespace, so I go and look at the docs for `Base.Sys` (many clicks later - [https://ocaml.janestreet.com/ocaml-core/latest/doc/base/Base/Sys/index.html](https://ocaml.janestreet.com/ocaml-core/latest/doc/base/Base/Sys/index.html)) but `getenv` isn’t listed. But it is apparently there…

There must be a better way?

---

<div class="post-metadata">

**Author:** ![yawaramin](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/yawaramin/32/3384_2.png) [@yawaramin](https://discuss.ocaml.org/u/yawaramin)\
**Post date:** [April 22, 2019, 8:05pm UTC](https://discuss.ocaml.org/t/searching-for-functions/3698/2 "2019-04-22T20:05:17Z")

</div>

The Hoogle equivalent for OCaml is called odig: [https://erratique.ch/software/odig](https://erratique.ch/software/odig) . You can install it locally and have it generate documentation for all installed packages. However, generated documentation is not globally searchable (see last point). Besides that, there are a few other strategies:

- Familiarize yourself with the standard library that ships with every OCaml distribution: [https://caml.inria.fr/pub/docs/manual-ocaml/libref/](https://caml.inria.fr/pub/docs/manual-ocaml/libref/) . This is the equivalent of Haskell’s `base` package. The `Prelude` equivalent module is called `Pervasives`. You will find the `Sys` module here, and `getenv` in there.
- Keep [http://opam.ocaml.org/packages/](http://opam.ocaml.org/packages/) handy for when you’re given a package name to look up. Package documentation is mostly not uploaded to a central location like Haddock. (But people have been talking about setting that up at [docs.ocaml.org](http://docs.ocaml.org).) You’ll probably need to open up and search through `.mli` files once in a while.
- The old-style ocamldoc documentation pages (like the standard library I linked above) have very handy pages indexing types, values, and modules. However, the newer odoc documentation pages which are becoming the de facto standard do not, as of yet. There are a couple of issues tracking this.

---

<div class="post-metadata">

**Author:** ![sid](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/sid/32/1476_2.png) [@sid](https://discuss.ocaml.org/u/sid)\
**Post date:** [April 22, 2019, 8:50pm UTC](https://discuss.ocaml.org/t/searching-for-functions/3698/3 "2019-04-22T20:50:39Z")

</div>

Thanks for this useful question! I am curious (if you feel comfortable sharing) your interest in approaching OCaml via Haskell. What do you feel are some of OCaml’s advantages for your use case?

---

<div class="post-metadata">

**Author:** ![jmackie](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/jmackie/32/1548_2.png) [@jmackie](https://discuss.ocaml.org/u/jmackie)\
**Post date:** [April 23, 2019, 8:49am UTC](https://discuss.ocaml.org/t/searching-for-functions/3698/4 "2019-04-23T08:49:11Z")

</div>

Thanks for this! I’d like to see `odig` support some sort of search functionality, that would really help someone like myself get orientated quicker.

---

<div class="post-metadata">

**Author:** ![jmackie](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/jmackie/32/1548_2.png) [@jmackie](https://discuss.ocaml.org/u/jmackie)\
**Post date:** [April 23, 2019, 9:01am UTC](https://discuss.ocaml.org/t/searching-for-functions/3698/5 "2019-04-23T09:01:59Z")

</div>

At the moment I don’t have a use case in mind - I’ve just heard good things about ocaml and I’m curious to explore more. The language certainly has some cool features I’d like to have in Haskell (module functors, polymorphic variants, labelled arguments…etc), and without the zoo of extensions and exotic type-level things it does feel a bit more “industrial”. But I’m not sure I can give up purity having seen how useful it is in Haskell…

I have been particularly impressed by the Bucklescript project - specifically the quality of the generated JS code - and could see myself using that on the frontend for non-trivial projects.

---

<div class="post-metadata">

**Author:** ![dbuenzli](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/dbuenzli/32/18_2.png) [@dbuenzli](https://discuss.ocaml.org/u/dbuenzli)\
**Post date:** [April 23, 2019, 9:08am UTC](https://discuss.ocaml.org/t/searching-for-functions/3698/6 "2019-04-23T09:08:30Z")

</div>

> [@jmackie](#):
>
> Thanks for this! I’d like to see `odig` support some sort of search functionality,

I’d like to add that at some point aswell, but don’t hold your breath for now.

A low effort improvement with great usability returns would be for `odoc` to at least generate per package index pages (like `ocamldoc` did), [this issue](https://github.com/ocaml/odoc/issues/52) tracks this.

---

<div class="post-metadata">

**Author:** ![steinuil](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/steinuil/32/993_2.png) [@steinuil](https://discuss.ocaml.org/u/steinuil)\
**Post date:** [April 23, 2019, 9:37am UTC](https://discuss.ocaml.org/t/searching-for-functions/3698/7 "2019-04-23T09:37:03Z")

</div>

It would definitely be nice to have something like hoogle, with global function name and type signature search. Elm has [something like that](https://klaftertief.github.io/elm-search/) as well.

---

<div class="post-metadata">

**Author:** ![let-def](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/let-def/32/2948_2.png) [@let-def](https://discuss.ocaml.org/u/let-def)\
**Post date:** [April 23, 2019, 12:49pm UTC](https://discuss.ocaml.org/t/searching-for-functions/3698/8 "2019-04-23T12:49:47Z")

</div>

Merlin has a search feature, `:MerlinSearch` in vim or `M-x merlin-search` in emacs.  
The command takes a query which is a list of type names prefixed by `-` or `+`:

- `-` for the type of values you have and the function you are looking for can consume
- `+` for values you would like to get.

For instance, `:MerlinSearch -int +string` gives you ways to transform an integer to a string:

```auto
string_of_int V int -> string                   
Bytes.create V int -> bytes                    
BytesLabels.create V int -> bytes                    
String.create V int -> bytes                    
StringLabels.create V int -> bytes                    
Big_int.approx_big_int V int -> Big_int.big_int -> string
Num.approx_num_exp V int -> Num.num -> string        
Num.approx_num_fix V int -> Num.num -> string        
Ratio.approx_ratio_exp V int -> Ratio.ratio -> string    
Ratio.approx_ratio_fix V int -> Ratio.ratio -> string    
...

```

Parametric types are flattened (only variance is considered), so `String.concat` can be found with `-string -list +string`. I haven’t thought about filtering based on the name of values, but this should be easy to implement in a future version of merlin, e.g. `env -string +string` for finding string transformers that contains “env” in their name.

The UI has not seen much work and the search is blocking, which is not super convenient, help is welcome to improve that :).

---

<div class="post-metadata">

**Author:** ![yawaramin](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/yawaramin/32/3384_2.png) [@yawaramin](https://discuss.ocaml.org/u/yawaramin)\
**Post date:** [April 23, 2019, 7:59pm UTC](https://discuss.ocaml.org/t/searching-for-functions/3698/9 "2019-04-23T19:59:51Z")

</div>

That’s really cool. I’d like to play around with it on the command line, are there any docs? I looked at [https://github.com/ocaml/merlin/blob/master/doc/dev/PROTOCOL.md](https://github.com/ocaml/merlin/blob/master/doc/dev/PROTOCOL.md) and ran `ocamlmerlin single -commands-help`, but not seeing anything about a search functionality.

---

<div class="post-metadata">

**Author:** ![yawaramin](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/yawaramin/32/3384_2.png) [@yawaramin](https://discuss.ocaml.org/u/yawaramin)\
**Post date:** [April 23, 2019, 8:26pm UTC](https://discuss.ocaml.org/t/searching-for-functions/3698/10 "2019-04-23T20:26:20Z")

</div>

Never mind, I figured it out 🙂

```
echo '\n' | ocamlmerlin single search-by-polarity -position 0 -query "-int +string" | less

```

Output is JSON, so would look better with some formatting:

```
echo '\n' | ocamlmerlin single search-by-polarity -position 0 -query "-int +string" | jq . | less
```

---

<div class="post-metadata">

**Author:** ![akama](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/akama/32/1422_2.png) [@akama](https://discuss.ocaml.org/u/akama)\
**Post date:** [April 24, 2019, 3:46pm UTC](https://discuss.ocaml.org/t/searching-for-functions/3698/11 "2019-04-24T15:46:48Z")

</div>

Here are two small bash/zsh functions building on @yawaramin’s work that might be useful. They will display a list of functions + the signatures. `ocs` will only display the first 10 because I don’t always want to fill my screen where as `osca` will list them all.

```
ocs () { echo '\n' | ocamlmerlin single search-by-polarity -position 0 -query $1 | jq '.value.entries[] | "\(.name) = \(.desc)"' | head -n 10 }
ocsa () { echo '\n' | ocamlmerlin single search-by-polarity -position 0 -query $1 | jq '.value.entries[] | "\(.name) = \(.desc)"' }
```

---

<div class="post-metadata">

**Author:** ![yawaramin](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/yawaramin/32/3384_2.png) [@yawaramin](https://discuss.ocaml.org/u/yawaramin)\
**Post date:** [April 24, 2019, 4:56pm UTC](https://discuss.ocaml.org/t/searching-for-functions/3698/12 "2019-04-24T16:56:48Z")

</div>

Fantastic! Minor quibble, but I’d use `:` instead of `=` to separate the name and type. Also another option for the output is to pipe to `less`.

---

<div class="post-metadata">

**Author:** ![UnixJunkie](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/unixjunkie/32/638_2.png) [@UnixJunkie](https://discuss.ocaml.org/u/UnixJunkie)\
**Post date:** [April 25, 2019, 1:25am UTC](https://discuss.ocaml.org/t/searching-for-functions/3698/13 "2019-04-25T01:25:51Z")

</div>

Does it search through all the opam-installed libraries?  
Or just the currently opened project?  
Why not support plain type signatures like int -\> string, why do you need the - and +?  
I will give it a try for sure.

---

<div class="post-metadata">

**Author:** ![UnixJunkie](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/unixjunkie/32/638_2.png) [@UnixJunkie](https://discuss.ocaml.org/u/UnixJunkie)\
**Post date:** [April 25, 2019, 1:27am UTC](https://discuss.ocaml.org/t/searching-for-functions/3698/14 "2019-04-25T01:27:02Z")

</div>

Searching by type signatures would be super useful too.

---

<div class="post-metadata">

**Author:** ![UnixJunkie](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/unixjunkie/32/638_2.png) [@UnixJunkie](https://discuss.ocaml.org/u/UnixJunkie)\
**Post date:** [April 25, 2019, 1:29am UTC](https://discuss.ocaml.org/t/searching-for-functions/3698/15 "2019-04-25T01:29:07Z")

</div>

Honestly, the OCaml community doesn’t have something that come close to Haskell’s hoogle.  
Which is really annoying when you know the productivity boost hoogle allows…

---

<div class="post-metadata">

**Author:** ![let-def](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/let-def/32/2948_2.png) [@let-def](https://discuss.ocaml.org/u/let-def)\
**Post date:** [April 25, 2019, 6:28am UTC](https://discuss.ocaml.org/t/searching-for-functions/3698/16 "2019-04-25T06:28:58Z")

</div>

> Does it search through all the opam-installed libraries?  
> Or just the currently opened project?

It searches only in the project scope. This is a proof-of-concept, but it can easily be enhanced to do opam-wide search (I didn’t think about it because that I never felt the need).  
Also, the search space can easily be indexed (while right now it is doing linear search), so performance should not be a problem at scale. I need to talk to @dbuenzli about that :).

> Why not support plain type signatures like int → string, why do you need the - and +?

With the current spec, the search is directed by variance which more accurately reflects the flow of information than a mere `->`. If it is just about syntax, of course the query language can be reworked, it is just frontend work (similarly, Hoogle does not strictly search by signature and do some approximation).

By relying only on variance, values are found even if they execute in a different monad, are written in a continuation passing-style or need more contexts (e.g. a context value).  
Results can then be ranked by relevance (though that bit has subjective elements in it).

---

<div class="post-metadata">

**Author:** ![gndl](https://avatars.discourse-cdn.com/v4/letter/g/58f4c7/32.png) [@gndl](https://discuss.ocaml.org/u/gndl)\
**Post date:** [April 25, 2019, 9:22am UTC](https://discuss.ocaml.org/t/searching-for-functions/3698/17 "2019-04-25T09:22:08Z")

</div>

Even if the project looks asleep, it may be interesting to mention it here : [https://github.com/camlspotter/ocamloscope.2](https://github.com/camlspotter/ocamloscope.2).

---

<div class="post-metadata">

**Author:** ![Wilfred](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/wilfred/32/1353_2.png) [@Wilfred](https://discuss.ocaml.org/u/Wilfred)\
**Post date:** [April 25, 2019, 1:59pm UTC](https://discuss.ocaml.org/t/searching-for-functions/3698/18 "2019-04-25T13:59:36Z")

</div>

That’s really neat, but it’s not clear to me how to search for generic types.

For example, `M-x merlin-search RET -'a list +'a` gives me an error:

```auto
"exception":"Not_found
Raised at file \"src/ocaml/typing/405/ident.ml\", line 168, characters 6-21
Called from file \"src/ocaml/typing/405/env.ml\", line 183, characters 22-43
Called from file \"src/ocaml/typing/405/env.ml\" (inlined), line 1057, characters 2-57
Called from file \"src/ocaml/typing/405/env.ml\", line 1127, characters 26-50
Called from file \"src/analysis/polarity_search.ml\", line 83, characters 29-52
Called from file \"src/utils/std.ml\", line 100, characters 12-15
Called from file \"src/utils/std.ml\", line 102, characters 23-39
Called from file \"src/analysis/polarity_search.ml\", line 86, characters 17-62
Called from file \"src/frontend/query_commands.ml\", line 403, characters 6-125
Called from file \"src/utils/local_store.ml\", line 29, characters 8-12
Re-raised at file \"src/utils/local_store.ml\", line 37, characters 4-15
Called from file \"src/kernel/mocaml.ml\", line 40, characters 8-38
Re-raised at file \"src/kernel/mocaml.ml\", line 48, characters 4-15
Called from file \"src/frontend/new/new_commands.ml\", line 64, characters 15-53
Called from file \"src/utils/std.ml\", line 654, characters 8-12
Re-raised at file \"src/utils/std.ml\", line 656, characters 30-39
Called from file \"src/ocaml/utils/misc.ml\", line 30, characters 20-27
Re-raised at file \"src/ocaml/utils/misc.ml\", line 30, characters 50-57
Called from file \"src/frontend/new/new_merlin.ml\", line 97, characters 18-54
"

```

Does the search syntax support this? I had a look at the merlin README and wiki, but didn’t see anything about this feature.

---

<div class="post-metadata">

**Author:** ![let-def](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/let-def/32/2948_2.png) [@let-def](https://discuss.ocaml.org/u/let-def)\
**Post date:** [April 25, 2019, 2:00pm UTC](https://discuss.ocaml.org/t/searching-for-functions/3698/19 "2019-04-25T14:00:45Z")

</div>

No, type parameters are ignored. Just write `-list`.

---

<div class="post-metadata">

**Author:** ![Wilfred](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/wilfred/32/1353_2.png) [@Wilfred](https://discuss.ocaml.org/u/Wilfred)\
**Post date:** [April 29, 2019, 2:17pm UTC](https://discuss.ocaml.org/t/searching-for-functions/3698/20 "2019-04-29T14:17:18Z")

</div>

Aha, so it’s only concrete types? Could I find `List.for_all` and `List.exists` using this? In this case I have a function `'a -> bool` and a `'a list` and I was wondering if merlin search could handle this.

[Next page](https://discuss.ocaml.org/t/searching-for-functions/3698.md?page=2)
