Read, Eval, Print, Loop: REPL#

NOTE: Assume import Prelude in all examples unless otherwise noted.

Intro#

It takes some practice to get familiar about when you can use one of :type or :kind to inspect types, values, expressions and constructors.

$ spago repl
PSCi, version 0.14.5
Type :? for help

> :?           
The following commands are available:

    :?                        Show this help menu
    :quit                     Quit PSCi
    :reload                   Reload all imported modules while discarding bindings
    :clear                    Discard all imported modules and declared bindings
    :browse      <module>     See all functions in <module>
    :type        <expr>       Show the type of <expr>
    :kind        <type>       Show the kind of <type>
    :show        import       Show all imported modules
    :show        loaded       Show all loaded modules
    :show        print        Show the repl's current printing function
    :paste       paste        Enter multiple lines, terminated by ^D
    :complete    <prefix>     Show completions for <prefix> as if pressing tab
    :print       <fn>         Set the repl's printing function to <fn> (which must be fully qualified)

Further information is available on the PureScript documentation repository:
 --> https://github.com/purescript/documentation/blob/master/guides/PSCi.md

:type#

According to the help, :type is for expressions:

> :type 'a'
Char

> :type "w" 
String

> :type 'w'
Char

> :type "w"
String

> :type 1
Int

> :type 3.14
Number

> :type []
forall (t1 :: Type). Array t1

Then we try something like:

> :type 1 .. 3
  Unknown operator (..)

> :type range 1 3
  Unknown operator (..)

Wait! 1 .. 3 is an expression, and so is range 1 3. We just need to import range and its synonym .. from some module that offers a range function:

> import Data.List (range, (..))
> :type 1 .. 3
List Int

> :type range 1 3 
List Int

The fact is that .. is an infix synonym (or alias if you will) for range.

Since range is a function, it is a value, an since .. is a synonym for range, .. is a value too. Just remember that most non alphabetic function names are generally infix, and to get info on infix operators, we generally need to enclose them inside parenthesis:

> :type ..
Unexpected or mismatched indentation at line 1, column 1

> :type (..)
Int -> Int -> List Int

See how the same error and solution applies for compose, for example:

> :type <<<  
Unexpected or mismatched indentation at line 1, column 1

> :type (<<<)
forall (t33 :: Type) (a :: t33 -> t33 -> Type) (b :: t33) (c :: t33) (d :: t33). Semigroupoid @t33 a => a c d -> a b c -> a b d

You can take a look at .. in Pursuit, click view source and see it is defined as:

infix 8 range as ..

:kind#

As seen earlier, :kind shows the kind of a type.

It works for the types and type constructors. For example:

> :kind Array
Type -> Type

It means Array is a type constructor that is not fully realized (it means it is awaiting for more types) that takes a type which then return the fully realized type.

If we say Array, it is an array of what? Numbers? Chars? Strings? Or an array of lists? Or even an array of arrays? We don’t know that by simply saying Array. It needs a further type in order to be fully realized:

> :kind Array Char
Type

> :kind Array String
Type

> :kind Array (Array Int)
Type

When :kind <type> returns Type, you may rest assured you are dealing with a fully realized type. If it returns Type -> Type, it is awaiting one type argument in order to be fully realized. If it says Type -> Type -> Type, it means it is awaiting for two more type arguments in order to be fully realized, and so on and so forth.