Live data from Hacker News

Use Haskell for shell scripting

haskellforall.com

41–50 of 105 posts

Re: Use Haskell for shell scripting

#41
post #34
post #28

Earlier quoted context omitted.

Ada might have failed on OS, but that is just because few startups that based their workstation OS in UNIX succeeded in the market at large. C goes hand-in-hand with UNIX, so clearly no UNIX vendor would have it in their SDK and UNIX developers weren't willing to pay for tools. As history has shown, the moment UNIX vendors started doing "Home" and "Pro" editions, GCC got lots of help. As Ada talks at FOSDEM show, it…

I think there's much (~10x) more C code than Ada code everywhere where safety matters. (No hard data, just a feeling from experience - if you have hard data proving me wrong, do share.) Also, it's not just Unix that's written in C or a descendant - there's also, well, Windows, and a load of embedded RTOSes. If Ada made you as productive as C with extra benefits or something to that effect, you'd expect Ada to succeed…

> I think there's much (~10x) more C code than Ada code everywhere where safety matters

Probably, but using C dialects and certification processes that make C just look like Ada with another syntax.

http://www.misra-c.com/MISRAChome/tabid/181/Default.aspx

http://en.wikipedia.org/wiki/DO-178B

http://www.programmingresearch.com/solutions/medical-devices...

> Also, it's not just Unix that's written in C or a descendant - there's also, well, Windows, and a load of embedded RTOSes.

Windows did not exist when UNIX was created.

MS-DOS was based on CP/M which copied ideas from UNIX into home computers. So while C didn't had a special place in home computers, UNIX was gaining adoption in the enterprise even Microsoft had their own UNIX, Xenix.

Which they used to cross compile some of their MS-DOS applications.

So it was only natural that when they started developing Windows, they used their in-house languages and both Quick Basic and Quick Pascal were not that up to the task, leaving C as the option.

Embedded RTOS are traditionally POSIX compliant, wich leads again to C.

Microsof is actually moving away from C, this is why they don't care about compliance any longer and speak about C++ and .NET Native.

Even their latest C99 related changes are only related to what ANSI C++11/14 require and a few key open source projects that they wanted to see supported.

Which is kind of funny, because Microsoft was the last C compiler vendor in the home computing space, to add a C++ compiler to their tools, with Microsoft C/C++ 7.0.

> If Ada made you as productive as C with extra benefits or something to that effect, you'd expect Ada to succeed at the marketplace at a scale at least comparable to C's - especially with the government support it had which put C at a disadvantage, not?

Not if people are expected to pay for the compilers.

Re: Use Haskell for shell scripting

#42
post #14

I don't know much about Haskell, but I thought it had some properties to isolate side effects, but the code he gives: main = do cd "/tmp" mkdir "test" output "test/foo" "Hello, world!" -- Write "Hello, world!" to "test/foo" stdout (input "test/foo") -- Stream "test/foo" to stdout rm "test/foo" rmdir "test" sleep 1 die "Urk!" Clearly doesn't (it creates a directory, writes in a file, removes that file and that directo…

People are talking about monads and stuff like that. No need to worry about maths and words you don't need to know. That 'do' keyword up there indicates the start of a simple DSL. The DSL goes like this, every line is the beginning of a lambda. And the result of each lambda evaluation is passed into the next lambda.

So you get a sort of cascading scope of lambdas where the result of each lambda is available passed into the next. Each lambda depends on the evaluation of the previous one. Normally in Haskell functions are executed lazily, this structure forces the sequential evaluation.

So what are these cd, mkdir, output etc functions? They return an object with a specific type called 'IO'. This type is monadic, but that's irrelevant for now. Haskell as you know has no side effects in the language itself. The IO type basically is a command pattern, it says "execute this I/O with these parameters".

The monadic aspect of IO makes it so that at the end the commands will have accumulated in a list, of which you can get an item if you give it the results of the previous item. So that's what the main function returns, a list of commands with some lazily evaluated Haskell code in between them. Now comes the side effect part. The Haskell runtime system iterates over the list of commands and executes them. The result of each command is used to get the next command in the list.

So that's the core of the magic trick of monadic I/O, you make a lazy list of I/O commands, and have something external to the language execute those I/O commands, giving the results back to the language to get the next I/O command to execute.

Re: Use Haskell for shell scripting

#43
post #2

The tutorial does a great job of explaining why this is interesting: http://hackage.haskell.org/package/turtle-1.0.0/docs/Turtle-... For example, the pwd function returns a FilePath type rather than a String: Prelude Turtle> :type pwd pwd :: IO Turtle.FilePath The datefile function is also typed: Prelude Turtle> :type datefile datefile :: Turtle.FilePath -> IO UTCTime So this really does seem to structure the data pa…

Are those types just aliases of String?

What do you mean by "alias"?

Path carries String-like information, it can even be easily converted to and from strings. Yet, it's a strong type that won't let you write something like 'path file_contents' (although, with overloaded strings, you can do 'path "file_name"').

UTCTime is not String-like.

Re: Use Haskell for shell scripting

#44
post #10

I don't really see the point of this, apart from academic research values. POSIX shell is everywhere - your current Linux and OS X machines, old UNIX workstations, home routers, servers... Just drop in a file and it will probably run just fine, unless the author screwed something up completely. POSIX shell scripts are the perfect bootstrap mechanisms that will run almost anywhere regardless of architecture. Haskell,…

Fine, have shell scripts rm -rf $VARIABLE/* while other people try to create sane alternatives

Every few years someone writes a retarded install script that wipes your drive, it's like it's inevitable

Re: Use Haskell for shell scripting

#45

I like the Pattern thing. However, it seems to me that you're going to quickly run into trouble if you need to even vaguely emulate shell scripting. Shell utilities live and die by their options. It's unfortunate Haskell supports neither named arguments nor default values. Which means that in order to emulate options, you would need to pass records to your "shell" utility, which, on top of being cumbersome, forces yo…

If your arguments aren't exclusive, you can pass a list of algebraic data. If they are exclusive, you can construct a type for them.

Re: Use Haskell for shell scripting

#46

Earlier quoted context omitted.

Quite a lot of libraries here: https://wiki.haskell.org/Command_line_option_parsers

That's not the issue. The issue is that, if you want to simulate both "grep" and "grep -r", you need to different functions, or you need to have your "grep" function accept a record of parameters.

I'm not good enough haskell programmer, but there is possible solution (records as you mentioned).

    import Prelude hiding ((-))

    data Grep = Grep {isRecursive :: Bool, maxCount :: Maybe Int} --etc
        deriving (Show)
    grep = Grep False Nothing
    --short pseudonim
    r :: Grep -> Grep
    r command = command{isRecursive = True}
    m :: Int -> Grep -> Grep
    m num command = command{maxCount = Just num}
    
    (-) :: a -> (a -> a) -> a
    (-) command flag = flag command
    ourGrep = grep -m 50 -r 
    
    main = print ourGrep -- > Grep {isRecursive = True, maxCount = Just 50}
    
    --then we should write monad which execute that data

Re: Use Haskell for shell scripting

#47
post #16
post #10

I don't really see the point of this, apart from academic research values. POSIX shell is everywhere - your current Linux and OS X machines, old UNIX workstations, home routers, servers... Just drop in a file and it will probably run just fine, unless the author screwed something up completely. POSIX shell scripts are the perfect bootstrap mechanisms that will run almost anywhere regardless of architecture. Haskell,…

Because shell is so deficient that even for "simple" things it is really easy to screw up - when whitespace or special characters in filenames cause some case you overlooked to screw up due to terrible quoting rules, when missing arguments cause [1], when you accidentally put bashisms in scripts labeled /bin/sh, when you suddenly have to do some basic text parsing (e.g. extracting capture groups from a regex) and hav…

That's before you've even addressed the stultifying features of shell as a language: booleans and tests are odd, arrays are odder, they have things called "functions" which don't have return values, the list goes on. Basically if you're writing shell, you probably also have at least Perl available, and probably Python...

Re: Use Haskell for shell scripting

#48
post #2

The tutorial does a great job of explaining why this is interesting: http://hackage.haskell.org/package/turtle-1.0.0/docs/Turtle-... For example, the pwd function returns a FilePath type rather than a String: Prelude Turtle> :type pwd pwd :: IO Turtle.FilePath The datefile function is also typed: Prelude Turtle> :type datefile datefile :: Turtle.FilePath -> IO UTCTime So this really does seem to structure the data pa…

Are those types just aliases of String?

No. For example, a FilePath is (after resolving a few other type aliases)

  data Root
	  = RootPosix
	  | RootWindowsVolume Char
	  | RootWindowsCurrentVolume

  data FilePath = FilePath
	  { pathRoot        :: Maybe Root
	  , pathDirectories :: [String]
	  , pathBasename    :: Maybe String
	  , pathExtensions  :: [String]
	  }

Re: Use Haskell for shell scripting

#49
Haskell is low on boilerplate? Yes, in general I would agree. Those scripts however, all have to be prefixed with "{-# LANGUAGE OverloadedStrings #-} import Turtle main = do". This is tedious boilerplate.

Re: Use Haskell for shell scripting

#50

I like the Pattern thing. However, it seems to me that you're going to quickly run into trouble if you need to even vaguely emulate shell scripting. Shell utilities live and die by their options. It's unfortunate Haskell supports neither named arguments nor default values. Which means that in order to emulate options, you would need to pass records to your "shell" utility, which, on top of being cumbersome, forces yo…

If your arguments aren't exclusive, you can pass a list of algebraic data. If they are exclusive, you can construct a type for them.

> If your arguments aren't exclusive, you can pass a list of algebraic data.

Which you need to prefix to avoid clashes.

> If they are exclusive, you can construct a type for them.

Which is going to end up being a record, which:

- is awkward to build (compared to just giving options to a command or arguments to a function)

- will most likely need to be an instance of Default

- which needs to have its fields prefixed to avoid clashes

Starts to sound like an awful amount of boilerplate.

Post reply on HN