2015-11-08 63 views
0

比方說,我有這樣的事情在Java中:哈斯克爾替代虛擬方法和方法繼承

class A { 
    int v; 
    public A(int v) { 
     this.v = v; 
    } 
    public int a() { 
     return v; 
    } 
} 

class B extends A { 
    public B(int v) { 
     super(v); 
    } 
    @Override 
    public int a() { 
     return super.a() + 5; 
    } 
} 

我怎麼能這樣做在Haskell相似的地方?我有一個非常基本的理解類型類是什麼。我想用類似ArrayList<A>的對象(或Haskell中的[A])具有虛擬方法,這些方法將從超類繼承。

+8

面向對象編程和函數式編程有很大的不同。你不能指望什麼在一個範例中有意義的轉換到另一個範例;雖然可以用繼承將對象編碼到Haskell中,但它並不漂亮。如果你能夠給出一個更具體的例子說明你在現實中想要達到的目標 - 超越「你好世界」 - 我們或許能夠在如何實現這一功能風格方面提供更多的幫助。 –

+1

Haskell缺乏名義上的子類型,這使得不可能直接翻譯。在Haskell中,可以通過編寫「數據B = B A」和「實例B某事物(B a)=某事物+ 5」來模擬類似的系統。當然,還有其他的方式 - 你實際做的取決於你的特定用例,這是從這個玩具例子中不可能看出的。 – user2407038

+0

@Benjamin Hodgson謝謝你的回答,我想實現一個簡單的人生模擬。在這個模擬中必須是具有不同行爲的對象/生物,但他們必須繼承某種父親生物。在使用OOP的命令式語言中,通過超級調用可以輕鬆實現,但我不明白如何在haskell中執行此操作。 – Artem

回答

1

有那種工作像這樣的「模式」:

data Animal m = Animal { 
    makeSound :: m() 
} 

cat = Animal { 
    makeSound = print "Meow!" 
} 

dog = Animal { 
    makeSound = print "Woof!" 
} 

cow = Animal { 
    makeSound = print "Moo!" 
} 


animals = [cat, cat, dog, cow] 

main = mapM_ makeSound animals 

使用這個模式,你可以做一些更多或更少的瘋狂的事情如:

import Data.Maybe 

data I a = I { 
    f :: a, 
    sup :: Maybe (I a) 
} 

mkA = I { f = 10, sup = Nothing } 

mkB = let a = mkA in I { 
    f = 5 + f a, 
    sup = Just a 
} 

ls = [mkA, mkB, fromJust $ sup mkB] 

main = mapM_ (print . f) ls 

這種模式可以也可以用來實現類似「工廠」的功能:

import Data.IORef 

data Storage m a = Storage { 
    putData :: String -> m(), 
    readData :: m String 
} 

fileStorage path = Storage { 
    putData = \s -> writeFile path s, 
    readData = readFile path 
} 

inMemStorage ref = Storage { 
    putData = \s -> writeIORef ref s, 
    readData = readIORef ref 
} 

readStorage storage = readData storage 

chooseStorage "file" = return $ fileStorage "tmp.txt" 
chooseStorage "mem" = do 
    r <- newIORef "" 
    return $ inMemStorage r 

main = do 
    storage <- chooseStorage "mem" 
    putData storage "hi there" 
    txt <- readData storage 
    print txt 

基本上你定義了一個有趣的數據類型ctions作爲其成員,然後定義返回該數據類型實例的「構造函數」(它們只是常規函數)。

+0

謝謝,這正是我想要的,我也有已經按照你的建議做了。 – Artem