2013-10-23 110 views
3

什麼是最好的monadic類型來解釋單子類型的一些人誰不知道單子?我應該使用Haskell庫中的某些東西還是應該創建一些新類型?什麼是最好的monadic類型來解釋單子類型?

+0

越簡單越好,也許從Maybe開始吧?我想這取決於你真正想要展示給他們的東西 –

+5

我不認爲一個monad就足以實際「得到它」。假設最終目標是他們可以讀取類型爲Monad m => ... m ...的函數,而不僅僅是那些涉及'TheSpecificMonadYouChose a'的函數。 – delnan

+0

出於實用目的,我認爲'ReaderT'和'WriterT'的組合產生了「寫入和讀取」計算。 – josejuan

回答

3

我認爲激勵單子最好的辦法是,以顯示特定的語言多少嵌入式領域都有一個單子的結構:

  • 列表理解都是明顯的例子。
  • JS承諾與.then單子作爲綁定操作
  • Groovy的?.操作
  • 許多「精通」,在面向對象的語言界面是一元

使用單子可以嵌入彙編爲6502 into your program link甚至BASIC代碼link

monad模式可以讓你從你的代碼集中在importa上消除無關緊要的複雜性計算的詳細信息。

當您想創建自己的EDSL時,瞭解monad模式將很好地爲您服務。

1

這個Maybe monad是(在我看來)最容易理解的。一旦你通過(簡單)代數類型的概念,瞭解單粒子如何工作是相當簡單的。

如果有人無法理解的構造爲Maybe,你可以寫他們的類,它在本質上是相同的事情:

class Maybe(object): 
    def __init__(self, value=None): 
     self.__just = value 

    def just(self): 
     if self.isJust(): 
      return self.__just 
     else: 
      raise ValueError('None') 

    def isJust(self): 
     return self.__just is not None 

    def fmap(self, f): 
     if self.isJust(): 
      return Maybe(f(self.just())) 
     else: 
      return Maybe() 

    def bind(self, fM): 
     """fM must return a value of type Maybe""" 
     if self.isJust(): 
      return fM(self.just()) 
     else: 
      return Maybe() 

    def __repr__(self): 
     if self.isJust(): 
      return 'Just ({})'.format(self.just()) 
     else: 
      return 'Nothing' 


def head(some_list): 
    if len(some_list) == 0: 
     return Maybe() 
    else: 
     return Maybe(some_list[0]) 

def idx(some_list, i): 
    if idx < len(some_list): 
     return Maybe(some_list[i]) 
    else: 
     return Maybe() 


print head([1, 2, 3]).bind(
    lambda x: Maybe(2 * x)).bind(
    lambda x: Maybe(x + 1)).bind(
    lambda x: Maybe(x + 3)) 

print head([[1, 2, 3]]).bind(
    lambda xs: idx(xs, 0)).bind(
    head).bind(
    lambda x: 2 * x) 

print head([[1, 2, 3]]).bind(
    lambda xs: idx(xs, 1)).bind(
    head).bind(
    lambda x: 2 * x) 

這段代碼打印出來

Just (6) 
Nothing 
Nothing 

這與Haskell中的monod具有相同的功能(或多或少),只是使用類在Python中重新實現。 Haskell中的return函數被構造函數替換,>>=被替換爲.bind

1

我認爲重要的是讓monadic模式從實際使用中產生。選擇一些類型並指導某人去解決一元模式自然表達的問題可能會很有啓發性。

關閉我的頭頂,很容易引起爭論爲Maybe的好處,讓別人得到關注的嵌套錯誤處理明顯的效果,然後再談

case f x of 
    Nothing -> Nothing 
    Just y -> case g y of 
    Nothing -> Nothing 
    Just z -> case h z of 
     Nothing -> Nothing 
     Just q -> case r q of 
     Nothing -> Nothing 
     Just end -> end 

實際上是一個如何Haskell允許您抽象出非常非常常見的模式。

然後談談配置以及如何將Config數據類型傳遞給許多函數以供其操作。這很容易落得像

go config in = 
    let (x, y) = f config $ g config $ h config in 
    in finally config x (we'reDone config y) 

編寫代碼,但是這又是在Haskell一個非常常見的模式是很煩人,但對緩解冗長的共同戰略。

最後說說狀態突變爲鏈接的自同態像

let state4 = (modify4 . modify3 . modify2 . modify1 :: State -> State) state0 

,以及如何是相當惱人的,以及同時修復你的「改裝連鎖」的時間提前,而不允許你滾出去的任何信息中間步驟(至少不需要將它與您的狀態一起穿線)。

而且,這可以在Haskell中通過具有奇怪名稱的常見抽象模式非常均勻地解決。你聽說過Monad的故事,對吧?

0

我有一個更深刻的見解,就是monads可以被看作命令式編程語言,你可以編寫它。所以也許你應該與他們建立一種「語言」,以便他們掌握抽象的強大程度。

我認爲爲他們創建一種編程語言將是一個很好的視角。

例如,首先你加狀態

import Data.Map as M 
import Control.Monad 
import Control.Monad.State 
data Variable = IntV Int | StringV String .. 
type Context = M.Map String Variable 
type Program a = State Context a 

然後添加記錄:

類型程序= WriterT [字符串](國家上下文)一 日誌X =告訴[X]

然後添加例外:

類型節目A = WriterT [字符串](StateT上下文要麼)一個

然後你添加延續等

這樣,你可以告訴他們,你可以使用monads建立一個環境,這對你的問題是非常好的。在此之後,如果他們感興趣,可以向他們展示monad的解剖結構以及它們是如何構建的。

例如首先顯示Maybe monad。它給他們首先將純朗母版:

data Perhaps a = Sure a | Nope 
next (Sure a) f = f a 
next (Nope) f = Nope 

告訴他們如何通過拉姆達連鎖計算:

small x | x < 100 = Sure x 
     | otherwise = Nope 
between x y z | x < z < y = Sure z 
       | otherwise = Nope 

small 10 `next` (\b -> between 5 20 b) 

然後告訴他們你可以如何改變這個做記號:

small x `next` (\b -> between 5 20 b 
     `next` (\c -> between 10 14 c)) 

如果我們可以這樣寫:

small x -> \b -> 
between 5 20 b -> \c -> 
between 10 14 c 

然後介紹做記號:

b <- small x 
c <- between 5 20 b 
between 10 14 c 

現在他們已經發明瞭做記號你從那裏你可以解釋一些其他的單子。

+0

我知道這個例子有點愚蠢。 –