gpt4 book ai didi

haskell |将多个值分配给某物,以便它们可以作为单个参数传递给函数

转载 作者:行者123 更新时间:2023-12-02 15:12:10 27 4
gpt4 key购买 nike

是否可以通过以下方式在 Haskell 中“分配”和传递值:

foo :: Int -> Int -> Int
foo x y = x + y

bar :: ??
bar = 2 3 -- ??

foo bar == 5

Foo 是一些需要两个整数的函数。我想将这些整数分配给单个栏并将该栏传递给 foo 以便它可以产生结果。我想在不使用元组、新类型或值分离的情况下实现这一点,如下所示:

bar1 = 2
bar2 = 3
foo bar1 bar2 == 5

这个问题是出于好奇,没有任何实际原因。

最佳答案

有一个合理的答案:

Data.Tuple.uncurry :: (a -> b -> c) -> (a, b) -> c
data A; data B; data C
foo :: A -> B -> C
bar :: (A, B)
uncurry foo bar :: C

有一个奇怪的答案:

bar :: (A -> B -> c) -> c
bar f = f A B
bar foo :: C

这是作弊答案:

{-# LANGUAGE CPP #-}
#define bar A B
foo bar :: C
-- expansion: foo A B :: C
-- Don't try to use this in any other way!
-- (bar, 2) ~> (A B, 2) -> error
-- It's incredibly unhygienic and WILL explode at some point
-- You probably want to uppercase the name to make it stick out
-- Or maybe
#undef bar
#define AP2(x) (fst (x)) (snd (x))
bar :: (A, B)
foo AP2(bar) :: C
#define BAR AP2(bar)
foo BAR :: C
-- expansion: foo (fst (A, B)) (snd (A, B))

这是依赖的答案(这只是一个增强的uncurry):

{-# LANGUAGE DataKinds, FlexibleInstances, FlexibleContexts, FunctionalDependencies, GADTs, MultiParamTypeClasses, TypeOperators, UndecidableInstances #-}

data HList (xs :: [*]) where
Hil :: HList '[]
Hons :: x -> HList xs -> HList (x : xs)

class AppHList f (a :: [*]) r | f a -> r where
appHList :: f -> HList a -> r
instance AppHList x '[] x where
appHList x Hil = x
instance (f ~ (a -> b), a ~ x, AppHList b xs r) => AppHList f (x : xs) r where
appHList f (Hons x xs) = appHList (f x) xs

-- if it's not obvious, HLists of two elements are isomorphic to 2-tuples
-- toT (Hons a (Hons b Hil)) = (a, b)
-- toH (a, b) = (Hons a (Hons b Hil))
-- toT . toH = id = toH . toT
-- and we get
-- uncurry = (. toH) . appHList
-- so, on some level, they are the same

bar :: HList [A, B]
bar = Hons A$Hons B$Hil
appHList foo bar :: C

这是一个精神错乱的答案:

{-# LANGUAGE DataKinds, FlexibleInstances, GADTs, TypeOperators #-}
import GHC.TypeLits

class FooType t
foo :: t
-- GADTs is only here for the ~s, and they aren't really needed
-- They're only here to make foo (B, A) a "needed (A, B) got (B, A)"
-- instead of a "instance not found"
instance (a ~ A, b ~ B) => FooType ((a, b) -> C) where
foo (a, b) = foo a b
instance FooType (A -> B -> C) where
foo a b = _
-- This instance pulls in GHC.TypeLits, DataKinds, TypeOperators, and UndecidableInstances
-- all in the name of pretty error messages.
instance {-# OVERLAPPABLE #-} TypeError (Text "foo is a function from "
:<>: ShowType A
:<>: Text " and "
:<>: ShowType B
:<>: Text " to "
:<>: ShowType C
:$$: Text "It may not be given the type "
:<>: ShowType t
) => FooType t where
foo = undefined

真正的答案是:

没有。简单而彻底的事实是,foo 的类型中有两个 (->),这意味着您需要两个函数应用程序才能完全使用它。有各种各样的技巧(按顺序,uncurry,连续传递风格,超越语言来规避其规则,时髦的伪依赖类型“有趣的东西”,以及重载foo)将此负担转移到其他地方(分别在 uncurry 的定义中、在 bar 的定义中、在扩展的后 CPP 代码中、在 appHList 中,在 FooType 的一个实例中),但它们都没有真正实现您想要的效果。 (CPS 是落后的并且出了名的难以阅读,CPP 只是被破坏了,类型类的东西需要大量修改 foo (大多数语言扩展只是为了效果;告我吧),以及 uncurry 及其更高级的表兄弟 appHList 需要额外的函数调用)。

关于 haskell |将多个值分配给某物,以便它们可以作为单个参数传递给函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48370927/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com