2012-09-12 39 views
3

一個無點函數是否可以返回一個元組?例如,可以在以下被寫入pointfree式(其中,f1,f2和f3已經定義):Pointfree在Haskell中返回一個元組

(\t -> (f1 t, f2 t, f3 t)) 

在這種情況下,我的F1,F2,和F3 QUOT的組合物,MOD,* ,和一些整數。

(\f1,f2,f3 -> (\t -> (f1 t, f2 t, f3 t))) 

是一個更一般的情況,並就相當於

(\f1,f2,f3,t -> (f1 t, f2 t, f3 t)) 

命名的功能是確定的,但我的例子都是匿名的。 (命名的例子如下)

f x = (f1 x, f2 x, f3 x) 
f f1 f2 f3 x = (f1 x, f2 x, f3 x) 

編輯:我只是好奇的好玩,我不打算這樣做。

+2

順便說一句,不要使用'quot'和'mod'一起。使用''''和'rem'(或者只是'quotRem')或者使用'div'和'mod'(或者使用'divMod')。這些配對具有保證,即「Rem m n =(q,r)」意味着'n * q + r = m'(對於'divMod'也是如此)。 –

+0

好的,謝謝! –

+0

爲什麼有兩雙,順便說一句? –

回答

11

你可以寫

(\t -> (f1 t, f2 t, f3 t)) 

pointfree,這是

liftM (,,) f1 `ap` f2 `ap` f3 

apControl.MonadMonad(->) a的實例,從Control.Monad.Instances。一個稍微更可讀的形式可能是Control.Applicative變種

(,,) <$> f1 <*> f2 <*> f3 

您可以

(\f1 f2 f3 -> (\t -> (f1 t, f2 t, f3 t))) 

由於

\f1 f2 f3 -> (,,) <$> f1 <*> f2 <*> f3 
= \f1 f2 -> ((,,) <$> f1 <*> f2 <*>) 
= \f1 f2 -> (<*>) ((,,) <$> f1 <*> f2) 
= \f1 f2 -> ((<*>) . ((,,) <$> f1 <*>)) f2 
= \f1 -> (<*>) . ((,,) <$> f1 <*>) 
= \f1 -> (<*>) . (<*>) ((,,) <$> f1) 
= \f1 -> (((<*>) .) . (<*>) . (<$>) (,,)) f1 
= ((<*>) .) . (<*>) . (<$>) (,,) 

但嚴重的是,你不應該自由點,然後進一步。保持可讀性,這意味着一點點免費是好的,但不要過分。

+1

我認爲這個答案比我的好得多,我主要是轉發lambdabot給出的。特別是,我喜歡'Control.Applicative'變種! –

4

是的。 #haskell IRC頻道上的「lambdabot」IRC機器人實際上具有一項功能,可爲您提供給定功能的無點版本。根據你的情況,它說,

\x -> (f x, g x, h x) 

相當於

ap (liftM2 (,,) f g) h 
+0

我喜歡lambdabot如何使用函數monad。 –

2

你可以寫你的例子是這樣的:

\f1 f2 f3 t -> (,,) (f1 t) (f2 t) (f3 t) 

(,,)是3個參數,通常的功能,所以沒有什麼在使得其應用pointfree特殊。然而,它使用它的論點3次,所以這將是繁瑣的,它可能不值得。

#haskell的Lambdabot說它是(ap .) . liftM2 (,,)。享受:)

4

雖然應用性或單子版本更簡單和更短,使用Control.Arrow

uncurry (uncurry (,,)) . ((f &&& g) &&& h) 
也許暴露了「意義」(什麼屬性,你正在使用的Haskell類型的類別)的一種方式

儘管如此,pointfull版本仍然優越。

這也暴露了你所需要的Hask的「Cartesianess」,但並不是所有的「閉性」 Hask

arrowized :: Arrow cat => cat a a1 -> cat a b1 -> cat a b -> cat a (a1, b1, b) 
arrowized f g h => arr (uncurry (uncurry (,,))) . ((f &&& g) &&& h) 
2

的下面是對對方的回答一些闡述在這裏。

源代碼中的Control.Applicative我們發現

instance Applicative ((->) a) where -- (a ->) is meant here 
    pure = const 
    (<*>) f g x = f x (g x) 

liftA3 f a b c = f <$> a <*> b <*> c 

在GHCI,我們得到

Prelude Control.Applicative> :t liftA3 (,,) 
liftA3 (,,) :: (Applicative f) => f a -> f b -> f c -> f (a, b, c) 

因此,隨着(t->)fliftA3 (,,)只是工作:

liftA3 (,,) ~ (t->a) -> (t->b) -> (t->c) -> (t->(a,b,c)) 

即,調用liftA3 (,,) f1 f2 f3 t上同類型的輸入產生三(f1 t, f2 t, f3 t),給出三個功能:

Prelude Control.Applicative>liftA3 (,,) (:[]) (quot 12) (`rem`3) 4
([4],3,1)


那麼,它是如何工作的?截至liftA3的definiton,再<*>

liftA3 (,,) f g h t = ((((,,) <$> f) <*> g) <*> h) t 
    = (((,,) <$> f) <*> g) t (h t) 
    = (((,,) <$> f) t (g t) (h t) 

現在,(<$>) = fmapinstance Functor ((->) t)定義fmap = (.),所以我們繼續

= (((,,) . f) t (g t) (h t) 
    = (,,) (f t) (g t) (h t) 
    = (f t, g t, h t)