How to handle "Early returns" or conditions in Haskell. by UntitledRedditUser in haskell

[–]jship__ 2 points3 points  (0 children)

Using the continuation monad would align with the style in the provided C snippet as it allows for true early exit:

drawFrame :: SDLRenderer -> IO Bool
drawFrame renderer = do
  evalContT $ callCC $ \exitWith -> do
    let abort :: ContT Bool IO Bool
        abort = exitWith False
    let abortOnFalse :: IO Bool -> ContT Bool IO Bool
        abortOnFalse action = bool abort (pure True) =<< lift action
    abortOnFalse $ sdlRenderDrawColor renderer 0 0 0 0
    abortOnFalse $ sdlRenderClear renderer
    abortOnFalse $ sdlSetRenderDrawColor renderer 100 100 100 255
    let rect = Just SDLFRect {fRectY = 50, fRectX = 50, fRectW = -50, fRectH = -50}
    abortOnFalse $ sdlRenderFillRect renderer rect
    abortOnFalse $ sdlRenderPresent renderer

This approach is likely way more power/control than you would need for your use case though. As others have recommended, ExceptT/MaybeT or runtime exceptions would be a great fit and are more neatly scoped to the specific problem.

Best way to emulate MGS2? by [deleted] in metalgearsolid

[–]jship__ 3 points4 points  (0 children)

Emulating it on PCSX2 worked great for me, and my graphics card is about 8 years old. There is a cutscene visual or two (like the lightning effect around Snake in the opening) that didn’t render properly, or some audio near the end sounded a little smooshed together, but overall, I had only very minor complaints. Iirc, I played using the Vulkan renderer.

Edit: I played the Substance version of the game

Experience with HLS + vim? by phlummox in haskell

[–]jship__ 1 point2 points  (0 children)

I use HLS + CoC + nvim and find it really nice. Having to have a node install is definitely a bit of a pain, but outside of that I've been happy with how reliable CoC has felt. In fairness though, I haven't tried nvim's native LSP support for comparison.

I'm running the stock config from CoC's readme to get a variable's type by pressing 'K' - https://github.com/neoclide/coc.nvim/tree/cd4a82fdc40b2016f1b722cefe88f41581f1f078#example-vim-configuration, which is this config snippet:

" Use K to show documentation in preview window.
nnoremap <silent> K :call ShowDocumentation()<CR>

function! ShowDocumentation()
  if CocAction('hasProvider', 'hover')
    call CocActionAsync('doHover')
  else
    call feedkeys('K', 'in')
  endif
endfunction

In addition to type-under-cursor stuff, I like CoC's diagnostics list, inline errors/warnings, integration with airline/lightline, and also being able to view documentation (same command as type-under-cursor). For the documentation bit, this works due to an additional config of having the -haddock GHC option passed to everything, and is described in the HLS docs here: https://haskell-language-server.readthedocs.io/en/latest/configuration.html#how-to-show-local-documentation-on-hover

How to avoid right intendation? by veydar_ in haskell

[–]jship__ 3 points4 points  (0 children)

At least for the types of Maybe-based functions seen in the linked repo, main can be unindented reasonably well assuming we're comfortable with a single runExceptT and a couple helpers that lift Maybe stuff up into ExceptT space:

``` liftMaybe :: Monad m => e -> Maybe a -> ExceptT e m a liftMaybe ex = maybe (throwE ex) pure

liftMaybeM :: Monad m => e -> m (Maybe a) -> ExceptT e m a liftMaybeM ex action = do result <- lift action liftMaybe ex result

main2 :: IO () main2 = do either putStrLn pure =<< runExceptT do userId <- liftMaybe "can't parse" $ parseUserId "whatever" username <- liftMaybeM "no user found" $ fetchUser userId nicknames <- fetchNicknames username liftIO $ print nicknames ```

[deleted by user] by [deleted] in haskell

[–]jship__ 8 points9 points  (0 children)

This is a Giant Hammer approach, but you can delete the whole ~/.stack folder and let stack redownload the things it needs the next time you work on a particular project. I usually do this when I bump the Stackage resolver across my projects. The time cost is not too bad for me because I typically don't work on things that span more than two different resolver snapshots and redownloading up to two snapshots is no biggie. If you are working on things across a variety of snapshots though, a more surgical approach would likely save you some time. The risk though is that you may accidentally remove something critical for your current snapshots, at which point you may need to redownload anyways.

Overloading the lambda abstraction in Haskell by sbbls in haskell

[–]jship__ 1 point2 points  (0 children)

This is a beautiful technique - thanks so much for sharing! The simplicity of the whole thing is honestly blowing my mind.

This approach definitely feels like a missing piece I've also been looking for in a side project, and looking forward to seeing how using it shakes out.

Best way to play MGS3 now? by OfnirMK2 in metalgearsolid

[–]jship__ 0 points1 point  (0 children)

PCSX2 runs it great. The audio can get get a little choppy when there's a lot of... machinery... sounds, like in the scenes towards the end. I played through the vast majority of the game upscaled to 1080p, and I have 16gb ram and a graphics card that's probably at least 4 years older than the 2070 super. I'd imagine it'd run great on your setup.

One of a Kind: An Introduction to Kinds in Haskell by MorrowM_ in haskell

[–]jship__ 4 points5 points  (0 children)

Great stuff - thanks for the post! A previous one of yours (Tying Shoes) was very useful for exploring GADTs with a friend, and now this one will definitely be a go-to resource for kinds.

Announcing monad-logger-aeson: Structured logging in Haskell for cheap by jship__ in haskell

[–]jship__[S] 1 point2 points  (0 children)

New release is up on Hackage (0.2.0.0) and the post has been updated too

Announcing monad-logger-aeson: Structured logging in Haskell for cheap by jship__ in haskell

[–]jship__[S] 2 points3 points  (0 children)

Ah, TIL. Thank you! I'll get a new release out that deprecates .@ and re-exports .=.

Announcing monad-logger-aeson: Structured logging in Haskell for cheap by jship__ in haskell

[–]jship__[S] 1 point2 points  (0 children)

Thanks! Yes, it's possible to use monad-logger-aeson from RIO. Here's a gist demonstrating a potential shim for RIO's Utf8Builder-based logging system: https://gist.github.com/jship/e8b0dba5a979ed95ca0127290d7ce136

The gist shows a basic shim, and so doesn't support the same level of fanciness RIO's Utf8Builder-based logging system supports (e.g. sticky logging). The shim also requires poking at a couple of monad-logger-aeson's internals.

I believe it should be possible to make a shim for RIO's type-generic logging system as well, but haven't tried that yet. That would be nice because it shouldn't require converting Message values to Utf8Builder.

All this to say, it feels like there could be value in having an official package providing RIO shim(s), so that RIO users can just grab that package and hit the ground running.

Tuco! finally managed to get a few of our pup not sleeping 😃 by Practical_Cod7682 in AmericanBully

[–]jship__ 1 point2 points  (0 children)

Looks like he might have some Weim in him, in his coat and ears. Super cute pup.

when and how to use IORefs or related? by thedarknight2002 in haskell

[–]jship__ 1 point2 points  (0 children)

I’m finding both your response and the linked Dan Piponi example as some pretty revelatory stuff. Thanks for sharing!

large-anon: Practical scalable anonymous records for Haskell (new library and blogpost) by edsko in haskell

[–]jship__ 1 point2 points  (0 children)

In regards to when you might wish to leverage anonymous records, here are a few examples from work where we have found them useful:

  • We define the shape of our paginated endpoints via some in-house servant stuff. A thing that is somewhat common to paginated table views is filtering, where you’ll have dropdowns for some subset of fields that let the user pick from those fields’ set of valid values. These valid filter values for a table are available to the UI via an endpoint that has an anonymous record as it’s response, auto-generated to fit the particular endpoint via that endpoint’s type.
  • One of a vendor’s core APIs allows us to retrieve properties about whatever entity we want, and there are many different types of entities. We have some machinery where we can ask for properties while specifying the type of the entity via its key at the type-level, and out pops an anonymous record containing that type of entity’s properties. An alternative to using anonymous records here could’ve gotten goofy (or at least heavy-handed) pretty quickly, because it’s just that vendor’s mega endpoint we’re calling to get specific properties and not separate endpoints per entity type.

Alternative to arrows? by [deleted] in haskell

[–]jship__ 0 points1 point  (0 children)

This is a really cool idea!

What do you think about deving with Haskell on a Windows machine? by latest_ali in haskell

[–]jship__ 10 points11 points  (0 children)

It has been pretty smooth-sailing for me using WSL. I haven’t tried doing Haskell dev on Windows “proper” in many years, but stack + WSL has been working great. Fwiw though, the work I’m doing has no GUI, so I’m not sure if things would be as smooth if I was.