I am trying out haskell's kafka library from git and got this error.
To debug this error, i like to print stacktrace at the error line.
In python world, it is just,
import traceback; print traceback.print_exc()
(or) in java, it is
e.printStackTrace()
So, how to do the same in haskell world?
You can get stack traces in Haskell but it is not as convenient as just e.printStackTrace(). Here is a minimal example:
import Control.Exception
import Debug.Trace
getStack :: String -> SomeException -> IO a
getStack msg e = traceStack (show e) $ error msg
main :: IO ()
main = do
(head []) `catch` (getStack "error on main at head")
Finally, compile it with ghc -prof -fprof-auto StackTrace.hs and it will produce
Prelude.head: empty list
Stack trace:
Main.getStack (StackTrace.hs:5:9-56)
Main.main (StackTrace.hs:(8,9)-(9,74))
GHC.List.CAF (<entire-module>)
StackTrace.exe: error on main at head
Related
If I have nix installed, I can run pretty much any program, without having it "installed".
For instance a javascript program require node
//in file helloworld.js
const http = require('http'); // Loads the http module
http.createServer((request, response) => {
response.writeHead(200, {
'Content-Type': 'text/plain'
});
response.write('Hello, World!\n');
response.end();
}).listen(1337);
and I can directly run it with
$(nix-build -E "with import <nixpkgs> { };nodejs")/bin/node helloworld.js
For simple haskell, I can likewise both summon a haskell environment, and have it run directly with a bash script :
#! /usr/bin/env nix-shell
#! nix-shell -i runghc -p "haskellPackages.ghcWithPackages(p: with p; [type-level-sets])"
#! nix-shell -I nixpkgs=channel:nixos-21.11
-- courtesy jyrimatti https://gist.github.com/jyrimatti/bd139e91ed257d37bc57c08ac505fc3f
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE TypeApplications #-}
module Main where
import Data.Type.Set (Set(..), Proxy(..))
class Get a s where
get :: Set s -> a
instance {-# OVERLAPS #-} Get a (a ': s) where
get (Ext a _) = a
instance {-# OVERLAPPABLE #-} Get a s => Get a (b ': s) where
get (Ext _ xs) = get xs
main :: IO ()
main = do
let lst = Ext "hello" $ Ext 10 $ Empty
putStrLn $ show $ get #String lst
However, say my program is more complicated, like the webserver example, and I want to target a particular package set. now all my dependencies are picked from that vetted set of packages which are known to be compatible with each others.
With stack installed, this is easy :
#!/usr/bin/env stack
-- stack --resolver lts-18.21 script
-- this script makes use of the http-client library, which is in stackage
{-# LANGUAGE OverloadedStrings #-}
import qualified Data.ByteString.Lazy.Char8 as L8
import Network.HTTP.Simple
-- An equivalent pure haskell file can also be run as
-- stack runghc --package http-conduit -- http.hs
main :: IO ()
main = do
response <- httpLBS "http://httpbin.org/get"
putStrLn $
"The status code was: "
++ show (getResponseStatusCode response)
print $ getResponseHeader "Content-Type" response
L8.putStrLn $ getResponseBody response
Is there an equivalent for nix which would make it simple to (reliably !) launch some haskell program, along with its dependencies, without anything special installed apart from nix ?
I imagine something like :
#! /usr/bin/env nix-shell
#! nix-shell -i runghc -p "stackage.lts-18.21"
#! nix-shell -I nixpkgs=channel:nixos-21.11
-- this script makes use of the http-client library, which is in stackage
{-# LANGUAGE OverloadedStrings #-}
import qualified Data.ByteString.Lazy.Char8 as L8
import Network.HTTP.Simple
-- An equivalent pure haskell file can also be run as
-- stack runghc --package http-conduit -- http.hs
main :: IO ()
main = do
response <- httpLBS "http://httpbin.org/get"
putStrLn $
"The status code was: "
++ show (getResponseStatusCode response)
print $ getResponseHeader "Content-Type" response
L8.putStrLn $ getResponseBody response
When I typed following on ghci, the exception is raised:
Prelude> import Control.Exception
Prelude Control.Exception> readFile "test.txt" `catch` (const $ return "exception caught!" :: SomeException -> IO String)
"*** Exception: test.txt: hGetContents: invalid argument (invalid byte sequence)
I do not understand why the exception is not caught. I run the above with stack ghci command on Windows 7.
("test.txt" file contains some random Japanese Letters encoded in UTF8, but I expect exception should be caught anyway)
Can someone explain why?
Since readFile returns a lazy String, it won't evaluate the file content until it is used, in this case, when ghci prints it. You can catch it by forcing to evaluate its content.
import Control.Exception
import Control.DeepSeq
(readFile "test.txt" >>= evaluate . force) `catch` (const $ return "exception caught!" :: SomeException -> IO String)
This problem is caused by lazy IO and Windows' default locale encoding.
Contrary to your assumption, the file is actually read after readFile "test.txt"catch(const $ return "exception caught!" :: SomeException -> IO String).
By lazy IO, the content of file is read only when the result value is actually evaulated.
And the exception you met is caused only when reading the content (explain below).
Evaluating forcibly the file make the catch function do catch:
> (print . length =<< readFile "test.txt") `catch` (const $ putStrLn "Exception caught" :: SomeException -> IO ())
Exception caught
In this example, the file is actually read when applying length function, then caught by the catch function.
In addition, the exception is caused because some (perhaps the first) character of test.txt is incompatible with the default character encoding of the handle,
which is CP932 in Japanese Windows.
Try inserting some ASCII characters before the invalid Japanese characters,
then you'd find the exception is really thrown when printing (actually evaluating the content of test.txt):
$ cat .\test.txt
abc介
$ stack exec ghci
> import Control.Exception
> readFile "test.txt" `catch` (const $ return "exception caught!" :: SomeException -> IO String)
"abc\33673*** Exception: test.txt: hGetContents: invalid argument (invalid byte sequence)
If you can read Japanese, see the first section of https://haskell.jp/blog/posts/2017/windows-gotchas.html, written by me! :)
Suppose a large and complicated Haskell program produces a NaN sometime during the execution. How do I find where in my code this happened without spending a lot of time adding lots of NaN checks to my code? I'm only interested in debugging, so I don't care about portability or performance.
This was discussed five years ago on Haskell-cafe. A possible solution was proposed, but wasn't discussed further.
https://mail.haskell.org/pipermail/haskell-cafe/2011-May/091858.html
Below is my attempt to get a stack trace to the point where a NaN is generated (in a small example program) by using feenableexcept as suggested in the Haskell-cafe discussion:
-- https://www.gnu.org/software/libc/manual/html_node/Control-Functions.html
foreign import ccall "feenableexcept" enableFloatException :: Int -> IO Int
allFloatExceptions :: Int
allFloatExceptions = 1 {-INVALID-} + 4 {-DIVBYZERO-} + 8 {-OVERFLOW-} + 16 {-UNDERFLOW-}
main :: IO ()
main = do
_ <- enableFloatException allFloatExceptions
print $ (0/0 :: Double)
Unfortunately, running this code doesn't produce a stack trace :(
$ ghc -rtsopts -prof -fprof-auto testNaN.hs && ./testNaN +RTS -xc
[1 of 1] Compiling Main ( testNaN.hs, testNaN.o )
Linking testNaN ...
Floating point exception (core dumped)
I assume (but really have no idea) that I don't get a stack trace because the GHC runtime wasn't in control when the exception aborted the program. So next I tried using installHandler from System.Posix.Signals to try to make the program crash within GHC's runtime:
import qualified System.Posix.Signals as Signals
-- https://www.gnu.org/software/libc/manual/html_node/Control-Functions.html
foreign import ccall "feenableexcept" enableFloatException :: Int -> IO Int
allFloatExceptions :: Int
allFloatExceptions = 1 {-INVALID-} + 4 {-DIVBYZERO-} + 8 {-OVERFLOW-} + 16 {-UNDERFLOW-}
catchFloatException :: IO ()
catchFloatException = error "print stack trace?"
main :: IO ()
main = do
_ <- enableFloatException allFloatExceptions
_ <- Signals.installHandler Signals.floatingPointException (Signals.Catch catchFloatException) Nothing
print $ (0/0 :: Double)
Unfortunately, this results in a more mysterious error, and still doesn't give me a stack trace :(
$ ghc -rtsopts -prof -fprof-auto testNaN.hs && ./testNaN +RTS -xc
[1 of 1] Compiling Main ( testNaN.hs, testNaN.o )
Linking testNaN ...
testNaN: too many pending signals
I also tried using multiple threads. Most of the time the following happens.
$ ghc -rtsopts -prof -fprof-auto -threaded testNaN.hs && ./testNaN +RTS -xc -N2
[1 of 1] Compiling Main ( testNaN.hs, testNaN.o )
Linking testNaN ...
testNaN: lost signal due to full pipe: 8
testNaN: lost signal due to full pipe: 8
testNaN: lost signal due to full pipe: 8
... repeat many many times, very very fast
Although, once this happened.
http://pastebin.com/u3u2cnHE
Am I taking the right approach? Is there a way to modify my example so that I can get a stack trace?
I'm trying to use purescript-halogen in combination with websockets, but after several attempts I'm unable to make them work together.
I've seen this question on Thermite and websockets and Phil's answer regarding the Driver function. Halogen also has a Driver function, but I need to run the Driver function with the Aff effect, while purescript-websockets-simple uses the Eff effect.
I've no idea how to transform the synchronous callbacks of the websocket package to asynchronous code running in the Aff monad. Do I need to use an AVar? Do I need purescript-coroutines-aff? If so, how do I hook up these parts together?
Thanks in advance for any pointers in the right direction!
In this case you would indeed want to use purescript-aff-coroutines. That will get you a coroutine Producer that you can then hook up to a Consumer that pushes messages into the driver:
module Main where
import Prelude
import Control.Coroutine (Producer, Consumer, consumer, runProcess, ($$))
import Control.Coroutine.Aff (produce)
import Control.Monad.Aff (Aff)
import Control.Monad.Aff.AVar (AVAR)
import Control.Monad.Eff (Eff)
import Control.Monad.Eff.Exception (EXCEPTION)
import Control.Monad.Eff.Var (($=))
import Data.Array as Array
import Data.Either (Either(..))
import Data.Maybe (Maybe(..))
import Halogen as H
import Halogen.HTML.Indexed as HH
import Halogen.Util (runHalogenAff, awaitBody)
import WebSocket (WEBSOCKET, Connection(..), Message(..), URL(..), runMessageEvent, runMessage, newWebSocket)
----------------------------------------------------------------------------
-- Halogen component. This just displays a list of messages and has a query
-- to accept new messages.
----------------------------------------------------------------------------
type State = { messages :: Array String }
initialState :: State
initialState = { messages: [] }
data Query a = AddMessage String a
ui :: forall g. H.Component State Query g
ui = H.component { render, eval }
where
render :: State -> H.ComponentHTML Query
render state =
HH.ol_ $ map (\msg -> HH.li_ [ HH.text msg ]) state.messages
eval :: Query ~> H.ComponentDSL State Query g
eval (AddMessage msg next) = do
H.modify \st -> { messages: st.messages `Array.snoc` msg }
pure next
----------------------------------------------------------------------------
-- Websocket coroutine producer. This uses `purescript-aff-coroutines` to
-- create a producer of messages from a websocket.
----------------------------------------------------------------------------
wsProducer :: forall eff. Producer String (Aff (avar :: AVAR, err :: EXCEPTION, ws :: WEBSOCKET | eff)) Unit
wsProducer = produce \emit -> do
Connection socket <- newWebSocket (URL "ws://echo.websocket.org") []
-- This part is probably unnecessary in the real world, but it gives us
-- some messages to consume when using the echo service
socket.onopen $= \event -> do
socket.send (Message "hello")
socket.send (Message "something")
socket.send (Message "goodbye")
socket.onmessage $= \event -> do
emit $ Left $ runMessage (runMessageEvent event)
----------------------------------------------------------------------------
-- Coroutine consumer. This accepts a Halogen driver function and sends
-- `AddMessage` queries in when the coroutine consumes an input.
----------------------------------------------------------------------------
wsConsumer
:: forall eff
. (Query ~> Aff (H.HalogenEffects (ws :: WEBSOCKET | eff)))
-> Consumer String (Aff (H.HalogenEffects (ws :: WEBSOCKET | eff))) Unit
wsConsumer driver = consumer \msg -> do
driver $ H.action $ AddMessage msg
pure Nothing
----------------------------------------------------------------------------
-- Normal Halogen-style `main`, the only addition is a use of `runProcess`
-- to connect the producer and consumer and start sending messages to the
-- Halogen component.
----------------------------------------------------------------------------
main :: forall eff. Eff (H.HalogenEffects (ws :: WEBSOCKET | eff)) Unit
main = runHalogenAff do
body <- awaitBody
driver <- H.runUI ui initialState body
runProcess (wsProducer $$ wsConsumer driver)
pure unit
This should give you a page that almost immediately prints:
hello
something
goodbye
But it is doing everything you need, honest! If you use the producer with a "real" source you'll get something more like what you need.
I am trying to do a recursive descent of a directory structure using Haskell. I would like to only retrieve the child directories and files as needed (lazily).
I wrote the following code, but when I run it, the trace shows that all directories are visited before the first file:
module Main where
import Control.Monad ( forM, forM_, liftM )
import Debug.Trace ( trace )
import System.Directory ( doesDirectoryExist, getDirectoryContents )
import System.Environment ( getArgs )
import System.FilePath ( (</>) )
-- From Real World Haskell, p. 214
getRecursiveContents :: FilePath -> IO [FilePath]
getRecursiveContents topPath = do
names <- getDirectoryContents topPath
let
properNames =
filter (`notElem` [".", ".."]) $
trace ("Processing " ++ topPath) names
paths <- forM properNames $ \name -> do
let path = topPath </> name
isDirectory <- doesDirectoryExist path
if isDirectory
then getRecursiveContents path
else return [path]
return (concat paths)
main :: IO ()
main = do
[path] <- getArgs
files <- getRecursiveContents path
forM_ files $ \file -> putStrLn $ "Found file " ++ file
How can I interleave the file processing with the descent? Is the problem that the files <- getRecursiveContents path action gets performed before the following forM_ in main?
This is exactly the kind of problem that iteratees/coroutines were designed to solve.
You can easily do this with pipes. The only change I made to your getRecursiveContents was to make it a Producer of FilePaths and to respond with the file name instead of returning it. This lets downstream handle the file name immediately instead of waiting for getRecursiveContents complete.
module Main where
import Control.Monad ( forM_, liftM )
import Control.Proxy
import System.Directory ( doesDirectoryExist, getDirectoryContents )
import System.Environment ( getArgs )
import System.FilePath ( (</>) )
getRecursiveContents :: (Proxy p) => FilePath -> () -> Producer p FilePath IO ()
getRecursiveContents topPath () = runIdentityP $ do
names <- lift $ getDirectoryContents topPath
let properNames = filter (`notElem` [".", ".."]) names
forM_ properNames $ \name -> do
let path = topPath </> name
isDirectory <- lift $ doesDirectoryExist path
if isDirectory
then getRecursiveContents path ()
else respond path
main :: IO ()
main = do
[path] <- getArgs
runProxy $
getRecursiveContents path
>-> useD (\file -> putStrLn $ "Found file " ++ file)
This prints out each file immediately as it traverses the tree, and it does not require lazy IO. It's also very easy to change what you do with the file names, since all you have to do is switch out the useD stage with your actual file handling logic.
To learn more about pipes, I highly recommend you read Control.Proxy.Tutorial.
Using lazy IO / unsafe... is not a good way to go. Lazy IO causes many problems, including unclosed resources and executing impure actions within pure code. (See also The problem with lazy I/O on Haskell Wiki.)
A safe way is to use some iteratee/enumerator library. (Replacing problematic lazy IO was the motivation for developing these concepts.) Your getRecursiveContents would become a source of data (AKA enumerator). And the data will be consumed by some iterator. (See also Enumerator and iteratee on Haskell wiki.)
There is a tutorial on the enumerator library that just gives an example of traversing and filtering directory tree, implementing a simple find utility. It implements method
enumDir :: FilePath -> Enumerator FilePath IO b
which is basically just what you need. I believe you will find it interesting.
Also there is a nice article explaining iteratees in The Monad Reader, Issue 16: Iteratee: Teaching an Old Fold New Tricks by John W. Lato, the author of the iteratee library.
Today many people prefer newer libraries such as pipes. You may be interested in a comparison: What are the pros and cons of Enumerators vs. Conduits vs. Pipes?.
Thanks to the comment by Niklas B., here is the solution that I have:
module Main where
import Control.Monad ( forM, forM_, liftM )
import Debug.Trace ( trace )
import System.Directory ( doesDirectoryExist, getDirectoryContents )
import System.Environment ( getArgs )
import System.FilePath ( (</>) )
import System.IO.Unsafe ( unsafeInterleaveIO )
-- From Real World Haskell, p. 214
getRecursiveContents :: FilePath -> IO [FilePath]
getRecursiveContents topPath = do
names <- unsafeInterleaveIO $ getDirectoryContents topPath
let
properNames =
filter (`notElem` [".", ".."]) $
trace ("Processing " ++ topPath) names
paths <- forM properNames $ \name -> do
let path = topPath </> name
isDirectory <- doesDirectoryExist path
if isDirectory
then unsafeInterleaveIO $ getRecursiveContents path
else return [path]
return (concat paths)
main :: IO ()
main = do
[path] <- getArgs
files <- unsafeInterleaveIO $ getRecursiveContents path
forM_ files $ \file -> putStrLn $ "Found file " ++ file
Is there a better way?
I was recently looking at a very similar problem, where I'm trying to do a somewhat complicated search using the IO monad, stopping after I find the file I'm interested in. While the solutions using libraries like Enumerator, Conduit, etc. seem to be the best you could do at the time those answers were posted, I just learned IO became an instance of Alternative in GHC's base library about a year ago, which opens up some new possibilities. Here's the code I wrote to try it out:
import Control.Applicative (empty)
import Data.Foldable (asum)
import Data.List (isSuffixOf)
import System.Directory (doesDirectoryExist, listDirectory)
import System.FilePath ((</>))
searchFiles :: (FilePath -> IO a) -> FilePath -> IO a
searchFiles f fp = do
isDir <- doesDirectoryExist fp
if isDir
then do
entries <- listDirectory fp
asum $ map (searchFiles f . (fp </>)) entries
else f fp
matchFile :: String -> FilePath -> IO ()
matchFile name fp
| name `isSuffixOf` fp = putStrLn $ "Found " ++ fp
| otherwise = empty
The searchFiles function does a depth-first search of a directory tree, stopping when it finds what you're looking for, as determined by the function passed as the first argument. The matchFile function is just there to show how to construct a suitable function to use as the first argument for searchFiles; in real life you'd probably do something more complicated.
The interesting thing here is that now you can use empty to make an IO computation "give up" without returning a result, and you can chain computations together with asum (which is just foldr (<|>) empty) to keep trying computations until one of them succeeds.
I find it a little unnerving that the type signature of an IO action no longer reflects the fact that it may deliberately not produce a result, but it sure simplifies the code. I was previously trying to use types like IO (Maybe a), but doing so made it very hard to compose actions.
IMHO there's no longer much reason to use a type like IO (Maybe a), but if you need to interface with code that uses a type like that, it's easy to convert between the two types. To convert IO a to IO (Maybe a), you can just use Control.Applicative.optional, and going the other way, you can use something like this:
maybeEmpty :: IO (Maybe a) -> IO a
maybeEmpty m = m >>= maybe empty pure