Non-exhaustive pattern matching in Haskell - haskell

I am learning Haskell and wanted to write a simple program which just repeats each letter in a string twice.
I came up with this:
repl :: String -> String
repl " " = " "
repl (x:xs) = x:x:repl xs
When compiling, I didnt get any warning but a run-time error occurred when I did repl "abcd":
"abcd*** Exception: repl.hs:(2,1)-(3,23): Non-exhaustive patterns in function repl
Why did the compiler never report this and why is it ignored in Haskell when there are many languages like OCaml which clearly report this at compile time?

The pattern match warning is turned off by default. You can turn it on with the -fwarn-incomplete-patterns or as part of a larger bundle of warnings with -W and -Wall.
You can do this from ghci:
Prelude> :set -W
You can also pass the flag to ghc when you compile or include it as a pragma on top of your module:
{-# OPTIONS_GHC -fwarn-incomplete-patterns #-}
For your specific program, it should give the following warning:
/home/tjelvis/Documents/so/incomplete-patterns.hs:2:1: Warning:
Pattern match(es) are non-exhaustive
In an equation for ‘repl’: Patterns not matched: []

Related

How to run GHCi in command line like a regular shell command

Is there any way I can run GHCi on command line like a regular command in shell?
For example: :browse in GHCi - list all the function for specific module.
but I want to run it on shell, e.g.: ghci --browse "MyModule"
which lists all the functions for the module
I know hoogle can run it on shell, e.g: hoogle Monad
The easiest way is to pipe in the commands via standard input. In Bash this can be done nicely with a “here-string”:
$ ghci <<< ':t reverse'
GHCi, version 8.2.1: http://www.haskell.org/ghc/ :? for help
Loaded GHCi configuration from /home/sagemuej/.ghci
Loaded GHCi configuration from /home/sagemuej/.ghc/ghci.conf
Prelude> reverse :: [a] -> [a]
Prelude> Leaving GHCi.
Use verbosity 0 to avoid all the greeting stuff:
$ ghci -v0 <<< ':t reverse'
reverse :: [a] -> [a]

Is it possible to pass command line arguments when running Haskell code with `ghc -e`?

Intuitively, I've tried
$ ghc -e "import System.Environment" -e "getArgs" -- a b c
ghc: unrecognised flag: --
did you mean one of:
-n
-F
-v
Usage: For basic information, try the `--help' option.
$
...without success.
I was expecting the output to be along the lines of ["a","b","c"].
The docs here don't seem to mention any way to pass cli arguments through.
AFAIK piping in stdio works as expected.
And perhaps if it is not possible to pass in arguments with ghc -e, maybe it's still possible with ghci to supply both some code, some arguments to it, run, then exit?
To answer the second part of the question:
Prelude> :help :main
Commands available from the prompt:
…
:main [<arguments> ...] run the main function with the given arguments
…
Prelude> let main = System.Environment.getArgs >>= print
Prelude> :main foo bar
["foo","bar"]

Modifying Emacs Inferior Haskell processes to enable CPP processing

If we look at the source of The random package we have a file Random.hs. Because of CPP extensions one has to invoke ghci via the following command :
ghci -cpp Random.hs
Alternatively one can do :
ghci -cpp
and then from within ghci :
Prelude GOA> :load Random
[1 of 1] Compiling System.Random ( Random.hs, interpreted )
Ok, modules loaded: System.Random.
If I use Emacs Inferior Haskell mode (Emacs/Inferior Haskell processes) and I have
the source :
module Main where
import System.Random
gen = (random (mkStdGen 0)) :: (Bool,StdGen)
mymult :: Int -> Int
mymult x = 2 * x
main = do
print $ mymult 5
then upon typing the emacs command :
C-c C-l
which is inferior-haskell-load-file, ghci is opened in a subwindow in emacs. However if from within this window I type load Random.hs then I get the error message :
*Main GOA> :load Random.hs
Random.hs:1:2: lexical error at character 'i'
Failed, modules loaded: none.
How can I load Random.hs taking into account cpp extensions? Or alternatively how do I modify haskell-mode/inf-haskell.el such that ghci is invoked with the -cpp option upon typing C-c C-l, so that the command :load Random.hs can be executed without error?
The most reliable way is certainly to request CPP, along with other extensions, in the file header:
{-# LANGUAGE CPP #-}
#if __GLASGOW_HASKELL__ >= 701
{-# LANGUAGE Trustworthy #-}
#endif
-----------------------------------------------------------------------------
-- |
-- Module : System.Random
-- Copyright : (c) The University of Glasgow 2001
-- License : BSD-style (see the file LICENSE in the 'random' repository)
The random package only does this in the .cabal file.
The easiest way might be to simply turn CCP on permanently in all ghci sessions, by adding
:set -XCPP
to your ~/.ghci file.

Haskell greedy elem?

I love to use elem in haskell for catching IP:Port. However elem is "exact match", and I cannot find a way to split with : as delimiter? Any idea to work around this?
Kind Regards
Use break:
Prelude> break (==':') "192.168.0.1:5000"
("192.168.0.1",":5000")
Prelude> break (==':') "192.168.0.15"
("192.168.0.15","")
You might like the split package
bash> cabal update && cabal install split
bash> ghci
ghci> import Data.List.Split
ghci> splitOn ":" "192.168.0.1:9000"
["192.168.0.1","9000"]

Simple library to do UTF-8 in Haskell (since Streams no longer compile)

I just want to read (and maybe write) UTF-8 data. haskell.org still advertises System.Streams which does not compile with recent ghc:
% runhaskell Setup.lhs configure
Configuring Streams-0.2.1...
runhaskell Setup.lhs build
Preprocessing library Streams-0.2.1...
Building Streams-0.2.1...
[10 of 45] Compiling System.FD ( System/FD.hs, dist/build/System/FD.o )
System/FD.hs:138:22:
Couldn't match expected type `GHC.IOBase.FD'
against inferred type `FD'
In the first argument of `fdType', namely `fd'
In a 'do' expression: fd_type <- fdType fd
In the expression:
let
oflags1 = case mode of
ReadMode -> ...
WriteMode -> ...
ReadWriteMode -> ...
AppendMode -> ...
binary_flags | binary = o_BINARY
| otherwise = 0
oflags = oflags1 .|. binary_flags
in
do fd <- fdOpen filepath oflags 438
fd_type <- fdType fd
when (mode == WriteMode && fd_type == RegularFile)
$ do fdSetFileSize fd 0
....
Similar problem with Streams 0.1. I cannot get more recent versions since the official site is down:
% wget http://files.pupeno.com/software/streams/Streams-0.1.7.tar.bz2
--2009-07-30 15:36:14-- http://files.pupeno.com/software/streams/Streams-0.1.7.tar.bz2
Resolving files.pupeno.com... failed: Name or service not known.
wget: unable to resolve host address `files.pupeno.com'
A better solution? darcs source code?
Use the utf8-string or the more recent text package.
View the list of packages on hackage.
Edit:
L. Kolmodin is right: utf8-string or text is the right answer. I'll leave my original answer below for reference. Google seems to have steered me wrong in choosing IConv. (The equivalent of my IConv wrapper function is already in utf8-string as Codec.Binary.UTF8.String.encodeString.)
Here is what I've been using--I may not remember the complete solution, so let me know if you still run into problems:
From Hackage, install IConv. Unfortunately, Codec.Text.IConv.convert operates on bytestrings, not strings. I guess you could read files directly as bytestrings, but I wrote a converter since HaXml uses normal strings:
import qualified Data.ByteString.Lazy.Char8 as B
utf8FromLatin1 = B.unpack . convert "LATIN1" "UTF-8" . B.pack
Now, on Mac OS, you have to compile with
$ ghc -O2 --make -L/usr/lib -L/opt/local/lib Whatever.hs
Because there was some library conflict, I think with MacPorts, I have to point explicitly to the built-in iconv libraries. There is probably a way to always pass those -L flags to ghc, but I haven't looked it up yet.
utf-8 strings are just byte character sequences, so it should be possible to just read and write the strings as is. All of the first 127 characters, including whitespace, should be ascii. Of course, you would need your own functions for manipulating strings since they are now multi byte sequences.

Resources