Showing posts with label haskell. Show all posts
Showing posts with label haskell. Show all posts

Wednesday, May 6, 2009

fundep

FunctionalDependencies example:

> {-# LANGUAGE GeneralizedNewtypeDeriving
>     , FunctionalDependencies
>     , MultiParamTypeClasses #-}

> module Test where

> import Control.Monad.State
> import Control.Monad.Identity

> class (Monad m) => MonadFoo a m | m -> a where
> -- class (Monad m) => MonadFoo a m  where
>     -- save :: m [a]
>     save :: m ()

save has type (MonadFoo a m) => m () . And, although Foo (see below) is an instance of MonadFoo Char, GHC complains that there is No instance for (MonadFoo a Foo) arising from a use of 'save', if functional dependencies isn't used (see commented out code above).

One way to get around is to make save :: m [a] and explicitly annotate each usage of save with :: Foo String (see commented out code of action).

But, using functional dependencies, one can say that m uniquely identifies a. So, GHC will instantiate a with Char on Foo's save, since Foo is an instance of MonadFoo Char.

>     restore :: m [a]
>     push :: a -> m ()

> newtype FooT m a = FooT {
>     runFooT :: (StateT (String, Int) m) a
>     } deriving (Monad, Functor, MonadState (String, Int))

> instance (Monad m) => MonadFoo Char (FooT m) where
>     save = do
>         (current, _) <- get
>         put (current, 0)
>         -- return current
>     restore = do
>         (current, n) <- get
>         put (drop n current, 0)
>         return $ take n current
>     push x = do
>         (current, n) <- get
>         put (x : current, n + 1)

> newtype Foo a = Foo {
>     runFoo :: FooT Identity a
>     } deriving (Monad, Functor
>         , MonadState (String, Int), MonadFoo Char)

> action :: Foo String
> action = do
>     push 'a'
>     save
>     -- save :: Foo String
>     push 'b'
>     push 'c'
>     restore
> test = runIdentity $ runStateT (runFooT (runFoo action)) ("", 0)

Thursday, April 17, 2008

Niffy Template Haskell trick for better trace

This trick is by EvilTerran from #haskell freenode IRC channel.

A quick and dirty way to debug Haskell code is to use trace function from Debug.Trace module.

For example,

f (trace ("arg1: " ++ show arg1) arg1) arg2

would print

arg1: <actual value of arg1>

Usung Template Haskell, above code can be shortened.

> {-# LANGUAGE TemplateHaskell #-}

This means this code uses TemplateHaskell extension.

> module Trace where

Let's call the module Trace.

> import Language.Haskell.TH
> import Debug.Trace (trace)

And, import some modules.

> t name = [| trace ($(litE . StringL $ nameBase name)
>    ++ ": " ++ show $(varE name)) $(varE name) |]

Then, define the macro t that can be called as:

$(t 'varName)

And it'll be expanded to:

trace ("varName" ++ ": " ++ show varName) varName

Let's actually use Trace.t in Main module.

> {-# LANGUAGE TemplateHaskell #-}

Main module also needs to use TemplateHaskell extension because it'll include macro call like $(t 'a).

> module Main where
> import Trace (t)
> import Debug.Trace (trace)

> main = do
>     let a = 2
>     let bravo = 40
>     putStrLn $ show ((trace ("a: " ++ show a) a) + bravo)

compare this with

>     putStrLn $ show ($(t 'bravo) + $(t 'a))

>     return ()

Shorter.

Now, I need vim keyboard shortcut that'll replace the word under cursor with $(t 'wordUnderCuror). And, another keyboard shortcut that'll turn $(t 'word) into word.

Edit: Alok commented with vim function below:

" word <===> $(t 'word)
" by Alok
function! ToggleTrace()
    call searchpos('\|)')
    let b = searchpos('\<', 'b')
    let s = searchpos("\$(t '", 'b')
    if s[0] == b[0] && b[1] - s[1] == len("$(t '")
        " remove trace
        norm df'f)x
    else
        " add trace
        call insert (b, 0, 0)
        call add (b, 0)
        call setpos('.', b)
        let @z = "$(t '"
        norm "zP
        let @z = ")"
        norm f "zP
    endif
endfunction

nmap <leader>t :call ToggleTrace()<cr>

Thank you Alok.

Monday, August 20, 2007

gtk2hs compiled!!

I tried to install gtk2hs for a couple of days. And finally, it succeeds! Somehow, I had to turn off compiler optimization (-O0). Here is PKGBUILD for Archlinux:

pkgname=gtk2hs
pkgver=0.9.12
pkgrel=1
pkgdesc="A GUI Library for Haskell based on Gtk"
url="http://haskell.org/gtk2hs/"
license=('GPL')
depends=('ghc' 'gtk2' 'libglade' 'librsvg' 'gtkglext' 'cairo' 'gtksourceview')
arch=('i686')
source=($pkgname-$pkgver.tar.gz)
install=gtk2hs.install
md5sums=('32752a42c225f55b0280151f8e19a3ed')
build() {
    cd $startdir/src/$pkgname-$pkgver
    ./configure --prefix=/usr --without-pkgreg --disable-split-objs --with-hcflags=-O0
    make || return 1
    make DESTDIR=$startdir/pkg install
}

This is gtk2hs.install file. Without --force, it fails somehow.

post_install() {
    for pkg in /usr/lib/gtk2hs/*.package.conf; do
        ghc-pkg register "$pkg" -g --force
    done
}

post_upgrade() {
    for pkg in /usr/lib/gtk2hs/*.package.conf; do
        #basename $pkg .package.conf
        tmp="${pkg##*/}"
        ghc-pkg unregister "${tmp%%.*}" && ghc-pkg register "$pkg" -g --force
    done
}

pre_remove() {
    for pkg in /usr/lib/gtk2hs/*.package.conf; do
        tmp="${pkg##*/}"
        ghc-pkg unregister "${tmp%%.*}" -g #2>/dev/null
    done
    rm /usr/lib/gtk2hs/*.o
}

op=$1
shift
$op $*

Now, haskell with gui goodness.