216 lines
5.3 KiB
Plaintext
216 lines
5.3 KiB
Plaintext
* Usage of Emacs front-end
|
|
|
|
** Key bindings
|
|
|
|
?M-C-i
|
|
!Completes a name of keyword, module, class, function, types, language extensions, GHC flags, etc.
|
|
?M-/
|
|
!Completes a name of local symbol.
|
|
?M-t
|
|
!Inserts template. In the beginning of a buffer, "module Foo where" is inserted. On the function without signature, inferred type is inserted. On a symbol "foo" without definition, "foo = undefined" is inserted or a proper module is imported. C-uM-t inserts a hole in this case. On a variable, the case is split. When checking with hlint, original code is replaced with hlint's suggestion if possible.
|
|
?M-C-d
|
|
!Browses the local document with your browser. On a module import line, the document of the module is browsed. On a function or type, its document is browsed.
|
|
?C-uM-C-d
|
|
!Browses the Hackage document of the module with your browser.
|
|
?M-C-m
|
|
!Loads information of symbols for modules in the current buffer. If you add a new line to import a module, type this. The idle timer executes this command anyway.
|
|
?C-cC-h
|
|
!Query somthing at the cursor for hoogle.
|
|
?C-xC-s
|
|
!Saves the buffer if necessary and runs syntax check.
|
|
?C-cC-c
|
|
!Toggle GHC and Hlint for syntax check. GHC is used for initial time.
|
|
?M-n
|
|
!Goes to the next warning or error.
|
|
?M-p
|
|
!Goes to the previous warning or error.
|
|
?M-?
|
|
!Displays the warning/error message in the current line.
|
|
?C-cC-i
|
|
!Displays the info of this expression in another window.
|
|
?C-cC-t
|
|
!Displays the type of this expression in the minibuffer. Type C-cC-t multiple time to enlarge the expression.
|
|
?C-cC-a
|
|
!Selects one of possible cases.
|
|
?C-cC-f
|
|
!Replaces a hole with user-typed functions followed by holes.
|
|
?C-cC-e
|
|
!Displays the expanded Template Haskell.
|
|
?C-cC-m
|
|
!Insert "import Module" for the function at the cursor.
|
|
?M-s
|
|
!Sort and merge import statements in the region.
|
|
?C-cC-j
|
|
!In the beginning of the buffer, errors of other files are displayed. Typing C-cC-j on the errors jumps to the fist file of the error sources.
|
|
?C-cC-k
|
|
!Kill the ghc-modi subprocess for this project. If you install dependency packages, this command should be executed to reflect that change.
|
|
?C-c<
|
|
!Make the indentation of the region shallower.
|
|
?C-c>
|
|
!Make the indentation of the region deeper.
|
|
|
|
** Resolving import hell
|
|
|
|
Here is an example story not to type "import Foo" when
|
|
you write a Haskell program.
|
|
|
|
Type the following signature.
|
|
Note that "ByteString" can be completed with M-C-i.
|
|
|
|
>|
|
|
foo :: [ByteString] -> [ByteString] -> [ByteString]
|
|
|<
|
|
|
|
C-xC-s highlights the signature.
|
|
Typing M-t on the line results in:
|
|
|
|
>|
|
|
import Data.ByteString (ByteString)
|
|
|
|
foo :: [ByteString] -> [ByteString] -> [ByteString]
|
|
foo = undefined
|
|
|<
|
|
|
|
Type M-C-m to load symbols of Data.ByteString.
|
|
Then edit the body of "foo".
|
|
Note that "append" can be completed with M-C-i.
|
|
|
|
>|
|
|
import Data.ByteString (ByteString)
|
|
|
|
foo :: [ByteString] -> [ByteString] -> [ByteString]
|
|
foo bs1 bs2 = B.append <$> bs1 <*> bs2
|
|
|<
|
|
|
|
C-xC-s highlights the body.
|
|
Type M-t to get:
|
|
|
|
>|
|
|
import Data.ByteString (ByteString)
|
|
import Control.Applicative ((<*>))
|
|
import Control.Applicative ((<$>))
|
|
import qualified Data.ByteString as B
|
|
|
|
foo :: [ByteString] -> [ByteString] -> [ByteString]
|
|
foo bs1 bs2 = B.append <$> bs1 <*> bs2
|
|
|<
|
|
|
|
Now select a region for import statements (for instance,
|
|
move the cursor, type C-SPC, and move the cursor) then
|
|
type M-s.
|
|
|
|
>|
|
|
import Control.Applicative ((<$>), (<*>))
|
|
import Data.ByteString (ByteString)
|
|
import qualified Data.ByteString as B
|
|
|
|
foo :: [ByteString] -> [ByteString] -> [ByteString]
|
|
foo bs1 bs2 = B.append <$> bs1 <*> bs2
|
|
|<
|
|
|
|
**Type holes
|
|
|
|
Consider the following broken example:
|
|
|
|
>|
|
|
foo :: [a -> a] -> a -> a
|
|
foo xs = foldr bar id xs
|
|
where
|
|
bar = (:)
|
|
|<
|
|
|
|
C-xC-s highlights the 2nd line. C-c? displays the following:
|
|
|
|
>|
|
|
Couldn't match type `[a -> a]' with `a -> a'
|
|
Expected type: (a -> a) -> (a -> a) -> a -> a
|
|
Actual type: (a -> a) -> [a -> a] -> [a -> a]
|
|
...
|
|
|<
|
|
|
|
Even in this situation, C-cC-t on 'id' displays 'a -> a' in the minibuffer. GHC's -fdefer-type-errors enables this magic.
|
|
|
|
Also, you can make use of GHC's hole. Inserting "_" before "bar" and typing C-xC-s results in highlighting the second line again:
|
|
|
|
>|
|
|
foo :: [a -> a] -> a -> a
|
|
foo xs = foldr _bar id xs
|
|
where
|
|
bar = (:)
|
|
|<
|
|
|
|
C-c? displays:
|
|
|
|
>|
|
|
Found hole `_bar' with type: (a -> a) -> (a -> a) -> a -> a
|
|
Where: `a' is a rigid type variable bound by
|
|
the type signature for foo :: [a -> a] -> a -> a
|
|
at /Users/kazu/c.hs:3:8
|
|
Relevant bindings include
|
|
bar :: forall a. a -> [a] -> [a] (bound at /Users/kazu/c.hs:6:5)
|
|
xs :: [a -> a] (bound at /Users/kazu/c.hs:4:5)
|
|
foo :: [a -> a] -> a -> a (bound at /Users/kazu/c.hs:4:1)
|
|
...
|
|
|<
|
|
|
|
**More type holes
|
|
|
|
Suppose you have:
|
|
|
|
>|
|
|
filterNothing :: [Maybe a] -> [a]
|
|
|<
|
|
|
|
Typing M-t gets:
|
|
|
|
>|
|
|
filterNothing :: [Maybe a] -> [a]
|
|
filterNothing = undefined
|
|
|<
|
|
|
|
On the other hand, typing C-uM-t gets:
|
|
|
|
>|
|
|
filterNothing :: [Maybe a] -> [a]
|
|
filterNothing xs = _body
|
|
|<
|
|
|
|
Then, C-xC-s refreshes highlightings. When you type C-cC-f on "_body" and
|
|
type "filter" in the minibuffer, you get:
|
|
|
|
>|
|
|
filterNothing :: [Maybe a] -> [a]
|
|
filterNothing xs = filter _body_1 _body_2
|
|
|<
|
|
|
|
** Case handling
|
|
|
|
Suppose you have:
|
|
|
|
>|
|
|
f :: [a] -> a
|
|
f x = _f_body
|
|
|<
|
|
|
|
Typing M-t on "x" splits cases as follows:
|
|
|
|
>|
|
|
f :: [a] -> a
|
|
f [] = _f_body
|
|
f (x:xs) = _f_body
|
|
|<
|
|
|
|
Suppose you have:
|
|
|
|
>|
|
|
f :: a -> Maybe a
|
|
f x = _f_body
|
|
|<
|
|
|
|
Typing C-cC-a on "_f_body" and selecting one of possible cases in another window results in:
|
|
|
|
>|
|
|
f :: a -> Maybe a
|
|
f x = Nothing
|
|
|<
|