(dhall-lsp-server) Blog post on "Implementing the Type-on-Hover feature"

Hey all!

I wrote my first “proper” (i.e. more than one paragraph plus an animated image) blog post concerning my work on dhall-lsp-server. Have a look—I would love some feedback!

6 Likes

My main feedback is when presenting code within a blog post, I recommend deviating a bit from the original code to improve the presentation. This is because the audience for a blog post is different than the audience for a contributor to the dhall-haskell project.

Some ways you can do this are:

  • Use blank lines more generously

    For example, instead of:

    -- Dhall.LSP.Backend.Typing ll. 35-46
    typeAt' pos ctx (Let (Binding x _ a :| []) e@(Note src _)) | pos `inside` src = do
      _A <- typeWithA absurd ctx a
      t <- fmap normalize (typeWithA absurd ctx _A)
      case t of
        Const Type -> do  -- we don't have types depending on values
          let ctx' = fmap (shift 1 (V x 0)) (insert x (normalize _A) ctx)
          _B <- typeAt' pos ctx' e
          return (shift (-1) (V x 0) _B)
        _ -> do  -- but we do have types depending on types
          let a' = shift 1 (V x 0) (normalize a)
          typeAt' pos ctx (shift (-1) (V x 0) (subst (V x 0) a' e))
    

    … you can do:

    -- Dhall.LSP.Backend.Typing ll. 35-46
    typeAt' pos ctx (Let (Binding x _ a :| []) e@(Note src _)) | pos `inside` src = do
      _A <- typeWithA absurd ctx a
    
      t <- fmap normalize (typeWithA absurd ctx _A)
    
      case t of
        Const Type -> do  -- we don't have types depending on values
          let ctx' = fmap (shift 1 (V x 0)) (insert x (normalize _A) ctx)
    
          _B <- typeAt' pos ctx' e
    
          return (shift (-1) (V x 0) _B)
    
        _ -> do  -- but we do have types depending on types
          let a' = shift 1 (V x 0) (normalize a)
    
          typeAt' pos ctx (shift (-1) (V x 0) (subst (V x 0) a' e))
    

    The reason why is that your audience will consist of a high proportion of people who know little to no Haskell and their untrained eye will have more difficulty parsing things without whitespace as a guide.

  • Use full words

    a.k.a. german naming convention

    For example:

    -- Dhall.LSP.Backend.Typing ll. 35-46
    typeAt' position context (Let (Binding x _ a :| []) expression@(Note source _)) | position `inside` source = do
      _A <- typeWithA absurd context a
    
      t <- fmap normalize (typeWithA absurd context _A)
    
      case t of
        Const Type -> do  -- we don't have types depending on values
          let newContext = fmap (shift 1 (V x 0)) (insert x (normalize _A) context)
    
          _B <- typeAt' position newContext expression
    
          return (shift (-1) (V x 0) _B)
    
        _ -> do  -- but we do have types depending on types
          let a' = shift 1 (V x 0) (normalize a)
    
          typeAt' position context (shift (-1) (V x 0) (subst (V x 0) a' expression))
    

    This is mainly because people who don’t contribute to the project regularly might not understand our internal naming conventions.

That definitely makes the code more accessible! Thanks for the feedback!

I particularly like the “german naming convention” xD

edit: I incorporated your suggestions. The code looks a lot less daunting now!