Фон
Я читаю в основном Адекватное руководство по функциональному программированию и делаю все упражнения. Я нахожусь в главе 9, Монадический лук, но мне сложно выполнять упражнения.
Упражнение 1
Рассматривая объект User следующим образом, используйте
safeProp
иmap/join
илиchain
, чтобы безопасно получить название улицы при задании пользователю:// safeProp :: String -> Object -> Maybe a const safeProp = curry((p, obj) => compose(Maybe.of, prop(p))(obj)); const user = { id: 1, name: 'Albert', address: { street: { number: 22, name: 'Walnut St', }, }, };
Решение 1
// getStreetName :: User -> Maybe String
const getStreetName = compose(
chain( safeProp( "name" ) ),
chain( safeProp( "street" ) ),
safeProp( "address" )
);
Это было легко. safeProp
возвращает монаду Maybe. Итак, при составлении safeProp
нам нужно использовать chain
(он же flatMap
) для продолжения, иначе вместо получения Maybe.of("value")
мы получим Maybe.of( Maybe.of("value") )
.
Выведенное правило: если вы хотите скомпоновать функцию A и функцию B, и обе возвращают монады, используйте chain
!
Упражнение 2.
Учитывая следующие функции, используйте getFile для получения пути к файлу, удалите каталог и оставьте только базовое имя, а затем просто запишите его. Подсказка: вы можете использовать
split
иlast
для получения базового имени из пути к файлу.// getFile :: () -> IO String const getFile = () => IO.of('/home/mostly-adequate/ch9.md'); // pureLog :: String -> IO () const pureLog = str => new IO(() => console.log(str));
Решение 2
const getBaseName = compose( last, split("/") );
const logFilename = compose(
chain( pureLog ),
map( getBaseName ),
getFile
);
Это немного сложнее, но я тоже справился.
Итак, getFile
возвращает монаду ввода-вывода. Но getBaseMap
возвращает только строку. Итак, у меня есть функция A, которая возвращает монаду, и функция B, которая возвращает примитивный тип. Я не могу составить их с помощью chain
, потому что функция B не имеет ничего, что нужно сглаживать. Это означает, что мне нужно map
, чтобы составить A и B!
Еще одно правило!
Теперь мне нужно составить B с помощью pureLog (C). После применения карты к B он вернет монаду ввода-вывода с преобразованным значением. Назовем это МБ. Учитывая, что мне нужно составить MB с помощью C (который возвращает монаду), я не могу применить правило 1 и просто использовать chain
.
Фух!
Пойдем к последнему!
Упражнение 3:
Учитывая следующие функции, используйте
validateEmail
,addToMailingList
иemailBlast
, чтобы создать функцию, которая добавляет новое электронное письмо в список рассылки, если он действителен, а затем уведомляет весь список.// validateEmail :: Email -> Either String Email // addToMailingList :: Email -> IO ([Email]) // emailBlast :: [Email] -> IO ()
Решение 3?
Понятия не имею, как это сделать ....
Вот что я сделал до сих пор:
// joinMailingList :: Email -> Either String (IO ())
const joinMailingList = compose(
chain( emailBlast ),
chain( addToMailingList ),
validateEmail
);
Но это неправильно. Я получаю следующую ошибку:
Функция имеет недопустимый тип; подсказка:
joinMailingList
должен возвращать Either String (IO ())
Вопросов:
- Как я могу это исправить? Может кто-нибудь объяснить мне, что не так?
- Должен ли я вывести дополнительные правила из предыдущих упражнений (не пропущено ли здесь какое-то правило компоновки)?
chain
предназначен для связывания эффекта (результата монадического вычисления) с другим действием. - person   schedule 19.05.2018