2015-12-25 39 views
3

我有兩個功能:組合(A - >也許一)和(a - > a)職能

f :: a -> Maybe a 
g :: a -> a 

我想創建這樣的功能:

h :: a -> Maybe a 

h x 
| isJust(f x) = Just (g $ fromJust(f x)) 
| otherwise = Nothing 

我該怎麼辦呢以更優雅的方式?

+7

優雅的方式發佈在下面。不過,我想提醒一下,使用'justJust/fromJust'可以說是最不優雅的方式。事實上,如果忘記「isJust」檢查,「fromJust」可能會導致程序崩潰。更好的方法是使用模式匹配來替代,例如沒有什麼 - >什麼都沒有;只是 - >只是$ g y'。另請參閱[布爾型失明](https://existentialtype.wordpress.com/2011/03/15/boolean-blindness/)瞭解更多信息。 – chi

+1

這是不正確的類型。 g(來自Just(f x)):a'。我認爲你只是(g(fromJust(fx))' –

回答

13

既然你已經標記爲這個問題:

h :: a -> Maybe a 
h = fmap g . f 

有關說明:

f   ::       a -> Maybe a 
g   ::  a ->  a 
fmap g  :: Maybe a -> Maybe a 
(.)   :: (Maybe a -> Maybe a) -> (a -> Maybe a) -> (a -> Maybe a) 
(.) (fmap g) ::       (a -> Maybe a) -> (a -> Maybe a) 
fmap g . f ::           (a -> Maybe a) 
h   ::           a -> Maybe a 

注意(.)的和fmap g的類型實際上是更普遍的:

(.) :: (b -> c) -> (a -> b) -> (a -> c) 
-- b in this case is Maybe a 
-- c in this case is Maybe a 

fmap g :: Functor f => f a -> f a 
-- f in this case is Maybe 

但是,你也可以對f結果模式匹配:

h x = 
    case f x of 
    Just k -> Just (g k) 
    _  -> Nothing 

請注意,您的原始示例甚至不會編譯,因爲g的返回類型不正確。

+0

我認爲這是最習慣的方式,並且表達了所有選項中最清楚的想法 – dfeuer

4

爲什麼不能簡單:

h :: a -> Maybe a 
h x = fmap g (f x) 

或運營商版本:

h :: a -> Maybe a 
h x = g <$> f x 
5

fmap2 :: (Functor g, Functor f) => (a -> b) -> g (f a) -> g (f b) 
fmap2 = fmap . fmap 

這裏是一個有趣的方式:

h :: a -> Maybe a 
h = fmap2 g f 

fmap2 g f ~> fmap (fmap g) f ~> fmap g . f ~> \x -> fmap g (f x)

Functor ((->) r)例如用在這裏:fmap可以用來代替(.)

+0

鑑於用戶(可能)是Haskell的新手,你會添加一些解釋嗎?不是每個人都熟悉'Functor(( - >)r)'。使用'b〜a','fa〜Maybe a'和'gc〜a - > c'會使這個更清晰 – Zeta

+0

@Zeta,我想讓它看起來像一個謎題 – user3237465

+0

因此,在'fmap。fmap'中左邊的'fmap'在'(a - >)'中,因爲'fmap g'總是一個函數,無論函數是什麼,右邊的'fmap'恰好在'Maybe'中(並且在owl combinator中,它也在(r - >)中。 –

相關問題