Возможность компоновки частичных функций в Haskell

Ниже мое решение для CTFP глава 4 проблемы который по сути включает составление частичных функций (которые не имеют определенных выходов для всех возможных входов, т.е. возвращают Maybe).

Задача состоит в том, чтобы реализовать композицию, идентичность (для удовлетворения требований категории) и опробовать ее с 2 частичными функциями. Поскольку я относительно новичок в Haskell, я надеялся получить общий обзор кода с предложениями по улучшению идиом и тестированию, которому я мог бы следовать. Ссылка на код

import Test.HUnit

module Main where

-- Given
safeRoot :: Double -> Maybe Double
safeRoot x 
  | x < 0     = Nothing
  | otherwise = Just (sqrt x)

-- Q1: Identity and composition
partialFnId :: a -> Maybe a
partialFnId x = Just x

partialFnCompose :: (b -> Maybe c) -> (a -> Maybe b) -> (a -> Maybe c)
partialFnCompose g f = x -> case (f x) of
                          Just value -> g value
                          Nothing -> Nothing

-- Testing Q1
testPartialFnMeetsCategoryRequirements1 = TestCase $ assertEqual "Id should pass through inputs" (Just 3) (partialFnId 3)
testPartialFnMeetsCategoryRequirements2 = TestCase $ assertEqual "Composition with identity is noop(1)" (Just 2.0) ((partialFnCompose partialFnId safeRoot) 4)
testPartialFnMeetsCategoryRequirements3 = TestCase $ assertEqual "Composition with identity is noop(2)" (Just 2.0) ((partialFnCompose safeRoot partialFnId) 4)

-- Q2: Implement safeReciprocal
safeReciprocal :: Double -> Maybe Double
safeReciprocal x
  | x == 0    = Nothing
  | otherwise = Just (1 / x)

-- Q3: Implement safeRootReciprocal via composing the above 2.
safeRootReciprocal :: Double -> Maybe Double
safeRootReciprocal = partialFnCompose safeRoot safeReciprocal

-- Testing Q3
testSafeRootReciprocal1 = TestCase $ assertEqual "Provides root of reciprocal for valid inputs" (Just 2.0) (safeRootReciprocal 0.25)
testSafeRootReciprocal2 = TestCase $ assertEqual "Provides Nothing on invalid inputs(1)" Nothing (safeRootReciprocal 0.0)
testSafeRootReciprocal3 = TestCase $ assertEqual "Provides Nothing on invalid inputs(2)" Nothing (safeRootReciprocal (-0.25))

main = do
  runTestTT $ TestList [testPartialFnMeetsCategoryRequirements1,
                        testPartialFnMeetsCategoryRequirements2,
                        testPartialFnMeetsCategoryRequirements3,
                        testSafeRootReciprocal1,
                        testSafeRootReciprocal2,
                        testSafeRootReciprocal3]

0

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *