簡體   English   中英

haskell-用關聯的二進制運算鏈接元素

[英]haskell - chain up elements with an associative binary operation

我是中級計划者,但只有Haskell初學者。 這是我的問題:

假設您有一個關聯的二進制運算,說(>>=) 是否有一個多元函數p使得p (>>=) hgfe = h >>= g >>= f >>= e

我問這個問題是因為這個問題表明二進制運算是否可以接受相同類型的輸入。 我想知道這是否可以一概而論。

EDIT-1:我嘗試修改http://okmij.org/ftp/Haskell/vararg-fn.lhs (可變類型自變量的可變數量部分)中的代碼,但進展甚微。

EDIT-2:稍微簡化代碼。

{-# LANGUAGE FunctionalDependencies, FlexibleInstances #-}


module Main where


class Lfold f a b | b -> a where 
  lfold :: (a -> (f a) -> (f a)) -> (f a) -> a -> b

instance Lfold f a (f a) where
  lfold op rid x = op x rid

instance Lfold f a b => Lfold f a (a -> b) where
  lfold op rid x y = lfold op (op x rid) y


test :: [String]
test = lfold (:) [] "a" "b" "c"

main :: IO ()
main = putStrLn $ show test

是的,您可以創建這樣的功能。 但是,這非常丑陋,您將需要顯式鍵入要傳遞的每個參數,以使編譯器找到正確的實例。

從您鏈接的多變量函數模板開始,我得出了

{-# LANGUAGE FlexibleInstances, InstanceSigs, MultiParamTypeClasses #-}

class ImplicitChain m a r where
  p :: m a -> r

instance Monad m => ImplicitChain m a (m a) where
  p :: m a -> m a
  p x = x

instance (Monad m, ImplicitChain m b r) => ImplicitChain m a ((a -> m b) -> r) where
  p :: m a -> (a -> m b) -> r
  p x f = p (x >>= f)


h :: Int -> [Int]
h = replicate 2
g :: Int -> [Int]
g = (:[])
f :: Int -> [Int]
f = flip enumFromTo 2

test :: [Int]
test = p [1::Int] h g f

但是您在問我們是否可以做更多的泛型運算,因此二進制運算也是一個參數。 是:

{-# LANGUAGE FlexibleInstances, InstanceSigs, MultiParamTypeClasses, UndecidableInstances #-}

class ImplicitVariadic a b r where
  p :: (a -> b -> a) -> r

instance ImplicitVariadic a b (a -> a) where
  p :: (a -> b -> a) -> a -> a
  p _ x = x

instance (ImplicitVariadic a b (a -> r)) => ImplicitVariadic a b (a -> b -> r) where
  p :: (a -> b -> a) -> a -> b -> r
  p f x y = p f (f x y)

您不能(至少不容易),因為您需要提前知道要處理多少個參數。 因為Haskell中的所有函數都是自動管理的,所以每個函數都只接受一個參數並返回一個值。 甚至是簡單的二進制運算符也可以接受一個參數(第一個操作數)並返回一個接受一個參數(第二個操作數)並返回結果的函數。 那是,

a + b == (+) a b
      == ((+) a) b

您的虛函數p無法從其第一個參數知道要給出多少個其他參數。 也就是說, p的類型應該是什么?

p :: (a -> a -> a) -> a                -- zero arguments?
p :: (a -> a -> a) -> a -> a           -- one argument?
p :: (a -> a -> a) -> a -> a -> a      -- two arguments?
p :: (a -> a -> a) -> a -> a -> a -> a -- three arguments?

取而代之的是,您能做的最好的就是使用fold,它需要一個操作和一個操作數列表

foldr (+) 0 [h, g, f, e] == h + g + f + e + 0  -- explicit first argument of 0
foldr1 (+) [h, g, f, e] == h + g + f + e -- assumes a list of at least one value

要了解“不容易”的含義,請查看Text.Printf模塊中printf的實現。 即使這樣也不是一個好例子,因為第一個參數攜帶的信息(格式字符串中占位符的數量)是僅二進制運算所不能提供的信息。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM