How to get the type of a term inside a do block in Leksah?

107 views Asked by At

Question in video format : http://youtu.be/3_pvK-gcLMM

Question in text format : how can I get Leksah to tell me the type of unlisten in the code below ?

Code is taken from https://github.com/SodiumFRP/sodium/blob/master/haskell/examples/tests/unit-tests.hs

If this is not possible with Leksah (to get a type of a term inside a do block) then how is it possible to extract that information ? Is there some other Haskell tool or IDE that can do that ?

module Main where

import FRP.Sodium
import Control.Applicative
import Control.Monad
import Control.Monad.Trans
import Data.Char
import Data.IORef
import Test.HUnit



main = do
          putStrLn "Give me a line"


event1 = TestCase $ do
    (ev, push) <- sync newEvent
    outRef <- newIORef ""
    sync $ do
        push '?'
    unlisten <- sync $ do
        push 'h'
        unlisten <- listen ev $ \letter -> modifyIORef outRef (++ [letter])
        push 'e'
        return unlisten
    sync $ do
        push 'l'
        push 'l'
        push 'o'
    unlisten
    sync $ do
        push '!'
    out <- readIORef outRef
    assertEqual "event1" "hello" =<< readIORef outRef

EDIT: It seems that haskell-vim-now can do it :

enter image description here

Would be nice to have the same in Leksah somehow.

1

There are 1 answers

0
Hamish Mackenzie On

This is a tricky problem with a number of different solutions (ghc-mod, ide-backend and others). Currently I think integrating ide-backend into Leksah is probably the best approach to fix this properly.

There is slightly clunky a work around that I find myself using some times. Specify the type to be () and let the compiler complain that it is not. For instance if you change the code so it is like this...

unlisten :: () <- listen ev $ \letter -> modifyIORef outRef (++ [letter])

You should get an error that includes the inferred type of unlisten. You may get an error asking you to turn on ScopedTypeVariables when you do this. If so, press Ctrl+R and Leksah should add {-# LANGUAGE ScopedTypeVariables #-} to the top of the file for you to switch it on.

One advantage of this approach is that it works even when your code is does not compile (I am not sure how well the other approaches cope with broken code).

I think you can also change it to a type hole by renaming unlisten to _unlisten, but that only works for names and not any expression and also if you don't rename all of the occurrences you might get a different inferred type.