Для получения полного доступа
зарегистрируйтесь.
RSS

Все сниппеты с тэгом «монады»



Сниппет,  Python

Монада IO

Gravatar image
Daniil Kolesnichenko
  • Репутация: 8
  • Сниппеты: 3
  • Ревизии: 0

Абстрактный класс Monad:

class Monad(object):
    @staticmethod
    def unit(value):
        raise NotImplementedError
        
    def bind(self, f):
        raise NotImplementedError
        
    def then(self, other):
        return self.bind(lambda _: other)

Собственно, монада IO:

class IO(Monad):
    def __init__(self, runIO):
        self.runIO = runIO
        
    @staticmethod
    def unit(value):
        return IO(lambda: value)
        
    def bind(self, f):
        @IO
        def newIO():
            return f(self.runIO()).runIO()
        return newIO

def runIO(m):
    return m.runIO()
    
def printIO(s, end='\n'):
    return IO(lambda: print(s, end=end))

@IO
def readIO():
    return input()

Использование:

users = {
    'admin': '1234',
    'begemot': '0000',
}

askPassword = (
    printIO('Введите логин: ', end='')
    .then(readIO)
    .bind(lambda login: (
        printIO('Введите пароль: ', end='')
        .then(readIO)
        .bind(lambda pw: IO.unit(pw == users.get(login, False)))
    ))
)

main = askPassword.bind(lambda p: printIO('Добро пожаловать!' if p else 'Неверный пароль'))

runIO(askPassword)

А так бы это выглядело на Haskell:

type Login = String
type Password = String

users :: [(Login, Password)]
users =
    [ ("admin", "1234")
    , ("begemot", "0000")
    ]
    
askPassword :: IO Bool
askPassword = do
    putStr "Введите логин: "
    login <- getLine
    putStr "Введите пароль: "
    password <- getLine
    return $ maybe False (\p -> p == password) $ lookup login users
    
main :: IO ()
main = do
    passwordIsCorrect <- askPassword
    putStrLn $ if passwordIsCorrect
        then "Добро пожаловать!"
        else "Неверный пароль"
Gravatar image
Daniil Kolesnichenko
  • Репутация: 8
  • Сниппеты: 3
  • Ревизии: 0

Использование:


def readMaybe(t, val):
    if type(t) == type:
        try:
            return Just(t(val))
        except:
            return Nothing()

val = (
    readMaybe(int, input())
    .bind(lambda x: readMaybe(int, input())
    .bind(lambda y: Just(x + y)))
)

print(val) # => Just <сумма чисел>, если были введены числа, иначе Nothing

Если первая введённая строка не распарсится как целое число, код не будет ждать ввода второй, а сразу кинет Nothing

class Just():
    def __init__(self, value):
        self.value = value

    def __str__(self):
        return "Just {value}".format(value=self.value)

    def bind(self, fn):
        return fn(self.value)

class Nothing():
    def __str__(self):
        return "Nothing"

    def bind(self, fn):
        return self