🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: pl.comp.lang.funkcyjne
Article #946

Programistyczna zagadka

#946
From: Michal Przybylek
Date: Fri, 25 Jul 2008 22:46
63 lines
2740 bytes
Poniżej kopia tego, co wysłałem przed chwilą na pl.comp.programming. Celem  
zabawy jest pokazanie, że jeżeli dostatecznie mocno się uprzeć, to nawet w  
Haskellu można wygodnie pisać w imperatywnym stylu.

***

Kiedy byłem studentem, jednym z ulubionych zadań gnębiących z semantyki i
weryfikacji, było podanie fragmentu programu w jakimś języku i pytanie o
to, co ten program robi. Ja proponuję trochę inną zabawę - poniżej jest
napisny mały program w Haskellu - oczywiście wiadomo co on robi. Pytaniem
jest dlaczego on robi to co robi. Miłej zabawy :-)


***
module Main (main)  where

import Control.Monad.Cont
import Control.Monad.State
import Data.Map
import IO (print)

infixr 0 <-:


-- nasze srodowisko bedzie zwyklym slownikiem odwzorowujacym
-- nazwy zmiennych w wartosci wstrzyknietym w monade stanu
getRef var = State $ \dict -> (Data.Map.lookup var dict, dict)
setRef var val = State $ \dict -> (Just val, insert var val dict)

-- podniesione przypisanie na zmienna / czytanie ze zmiennej
ref var = lift (getRef var)
var <-: val = lift (setRef var val)


-- definicja petli nieskonczonej
-- aby wykonac petle z cialem instr
--   wykonaj instr
--   wykonaj petle z cialem instr
loop :: ContT a (State s) a -> ContT a (State s) a
loop instr = instr >> loop instr


computeFact = callCC $ \exit ->
    loop $ do
      Just i   <- ref "i"      -- wez wartosc zmiennej "i"
      Just acc <- ref "acc"    -- wez wartosc zmiennej "acc"
      if i == 0
        then exit $ Just acc   -- wyskakujemy z petli z wynikiem acc
        else do
          "i"   <-: i-1        -- ustawiamy "i" na i-1
          "acc" <-: acc*i      -- ustawiamy "acc" na acc*i

fact n = k  where
    Just k = evalState (runContT computeFact return) initEnv
    initEnv = fromList [("i"  , n),
                        ("acc", 1)]

main = print $ fact 5

***

-- 
Michał Przybyłek
Technical Details
Message-ID: <op.uevdkkkxozidl8@dkd78.neoplus.adsl.tpnet.pl>
Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!newsfeed.gazeta.pl!wsisiz.edu.pl!newsfeed.neostrada.pl!atlantis.news.neostrada.pl!news.neostrada.pl!not-for-mail

Show Full Headers
Complete Article Headers
Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!newsfeed.gazeta.pl!wsisiz.edu.pl!newsfeed.neostrada.pl!atlantis.news.neostrada.pl!news.neostrada.pl!not-for-mail
From: "Michal Przybylek" <michal.przybylek@gmail.com>
Newsgroups: pl.comp.lang.funkcyjne
Subject: Programistyczna zagadka
Date: Sat, 26 Jul 2008 00:46:58 +0200
Organization: TP - http://www.tp.pl/
Lines: 63
Message-ID: <op.uevdkkkxozidl8@dkd78.neoplus.adsl.tpnet.pl>
NNTP-Posting-Host: dkd78.neoplus.adsl.tpnet.pl
Mime-Version: 1.0
X-Trace: atlantis.news.neostrada.pl 1217025677 3382 83.24.7.78 (25 Jul 2008 22:41:17 GMT)
X-Complaints-To: usenet@news.neostrada.pl
NNTP-Posting-Date: Fri, 25 Jul 2008 22:41:17 +0000 (UTC)
User-Agent: Opera Mail/9.51 (Win32)
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit