Perl: the super-convenient pseudo-functional language

Submitted by metaperl on Fri, 05/12/2006 - 10:55am.

I work at a place where we show adult models online. I was building our monthly newsletter and realized that of the 30 models who I could choose for the newsletter, not all of them had all 4 required pictures.

So I needed to hit our content server and see if a model had all 4 pictures. My knowledge of functional programming came in handy, but look how easy this was to code in Perl:


use LWP::Simple;

my @stream = qw(

# type ModelName = String
# type ImageNumber = Int
# type URLString = String
# img :: ModelName -> ImageNumber -> URLString
sub img {
my $s = shift;
my $i = shift;

my $prefix = substr $s, 0, 1 ;
$prefix = uc $prefix;


# does a model have all 4 images?
# good_imgs :: [ URLString ] -> Bool
sub good_imgs {
my $s = shift;
for my $i (1..4) {
my $img = img($s, $i), $/;
return undef unless get($img) ;
return 1;

# grep is like Haskell's filter
my @ok = grep { good_imgs($_) } @stream ;

# print the models with all 4 images
print join "\n", @ok ;

This is my first time seeing how great _Haskell_ really is. Those type signatures make my Perl self-documenting. But the thing is, there is nothing close to libwww-perl for Haskell. It not only makes HTTP requests but comes with a pragmatic parser for everyday HTML.

Another thing is look how I could list the model names without bothering with quotes around the strings. The qw() operator in Perl allows one to input a list of strings without quotes by simply separating them with whitespace.

unwords with optional record separator is hard to write?

Submitted by metaperl on Thu, 05/11/2006 - 10:29am.

I was chatting with Cale on #haskell and said that unwords should be configurable: it should take an optional argument specifying what to separate the elements of the list with.

He said that would be hard.

It is a common thing in Perl and Lisp for a function to assume defaults if you don't specify things.

I guess the best thing to do in Haskell is to always expect the separator to be specified and have the function curryable on the input list to be unworded:

unwords :: String -> [a] -> String
unwords sep lis = blah blah

extending howManyEqual

Submitted by metaperl on Mon, 05/08/2006 - 5:50pm.

howManyEqual a b c = fromEnum(a == b) + fromEnum(b == c) + fromEnum(a == c)

how would I write howManyEqualFour a b c d

abstracting the abstract

Submitted by metaperl on Thu, 05/04/2006 - 4:49pm.

Does anyone have any suggestions for making this code even more abstract?

-- concrete approach
twoThreeA1 = above (sideBySide white blackRectangle) (sideBySide blackRectangle white)
twoThreeA2 = sideBySide (above white blackRectangle) (above blackRectangle white)

-- abstract approach
twoThreeAg joiner builder = joiner (builder white blackRectangle) (builder blackRectangle white)
twoThreeA1g = twoThreeAg above sideBySide
twoThreeA2g = twoThreeAg sideBySide above

-- can we get more abstract?

The saga of my quest to understand the State monad

Submitted by metaperl on Wed, 04/26/2006 - 1:55am.

Part I:

-- Given this:

fmap :: (a -> b) -> (State s a) -> (State s b)
fmap f (State m) = State (onVal f . m)
where onVal f (x, s) = (f x, s)

-- problem 1: the type signature says that the ultimate return value is
-- (State s b) which would be this function : (\s -> (b,s))
-- However, the type of onVal is this:
-- :t onVal
-- onVal :: (a -> a1) -> (a, b) -> (a1, b)
-- In other words, it is just a 2-tuple. It is not clear that a 2-tuple
-- satisfies the expected type (State s b)

-- problem 2: I don't understand the expression (onVal f . m)
-- is this onval (f . m) or (onVal f) . m

modelling Camels : I started the convo, so I gotta chronicle it

Submitted by metaperl on Mon, 04/24/2006 - 8:51pm.

[19:43:51] /metaperl/ I was trying to make the leap from data Sheep = (name::String, mother::Maybe Sheep, father::Maybe Sheep) to camels....
[19:44:19] /Cale/ (that is, not quite fields)
[19:44:42] /sjanssen_/ metaperl: perhaps a good encoding is "data Camel a b c = Camel a b (Maybe c)"
[19:44:55] /metaperl/ sjanssen_: very clever!
[19:44:57] /metaperl/ :)
[19:45:42] /metaperl/ I like to name the type and data constructor distinctly though: data CamelType a b c = Camel a b (Maybe c)
[19:47:14] /Cale/ data Camel a b = Dromedary a | Bactrian a b
[19:47:45] /metaperl/ nice Cale
[19:49:25] /Cale/ I'm not sure what kind of Camel would have 3 humps though.
[19:49:31] /goltrpoat/ an Objective one.
[19:49:41] /Korollary/ A souped-up camel
[19:49:44] /Korollary/ long range
[19:49:52] /sjanssen_/ a camel with a massive tumor?
[19:50:20] /Cale/ an intercontinental ballistic camel
[19:50:29] /Lokadin/ lol
[19:51:06] /Cale/ the extra 'hump' is a warhead
[19:51:47] /goltrpoat/ embedded by INRIA

Catalog of computation strategies

Submitted by metaperl on Mon, 04/24/2006 - 2:38pm.
when something may or may not return a value
use Maybe

when something may return 0,1 or more values
use a List... but ask yourself: isn't Maybe just a subcase of list? We can restate Maybe as something which returns 0 or 1 value while we can see a list of something which may return 0..n values.
Pardon me while the brainstorm continues, but I just thought about the children of an n-ary tree - asking for children of a node returns a list which is a monad.

Why is + overloaded but / not?

Submitted by metaperl on Sun, 04/23/2006 - 11:09am.

*Main> 5/2
*Main> 5 `div` 2
*Main> 5.0 + 2.0
*Main> 5 + 2

A type constructor is better called a "type descriptor"

Submitted by metaperl on Sat, 04/22/2006 - 9:07am.

A type "constructor" just describes what a data constructor builds. It doesn't construct anything and shouldn't be called a constructor.

The Gematria of Satan Explored Through Haskell. in #haskell

Submitted by metaperl on Fri, 04/21/2006 - 5:37pm.

[16:40:15] ihope/ sum [1..sum [1..8]]
[16:40:17] lambdabot 666
[16:40:27] GeniXPro/ nice
[16:40:40] GeniXPro/ You created the best number!
[16:40:44] GeniXPro/ beast*
[16:40:58] ihope/ What a typo.
[16:43:38] ihope/ "This calls for wisdom. If anyone has insight, let him calculate the number of the beast, for it is man's number. His number is 666."