标签: polyvariadic

Haskell printf如何工作?

Haskell的类型安全性仅对于依赖类型的语言是首屈一指的.但是Text.Printf有一些深刻的魔力似乎相当类型.

> printf "%d\n" 3
3
> printf "%s %f %d" "foo" 3.3 3
foo 3.3 3
Run Code Online (Sandbox Code Playgroud)

这背后的深层魔力是什么?该Text.Printf.printf函数如何采用像这样的可变参数?

用于允许Haskell中的可变参数的一般技术是什么,它是如何工作的?

(旁注:使用这​​种技术时,某种类型的安全性显然会丢失.)

> :t printf "%d\n" "foo"
printf "%d\n" "foo" :: (PrintfType ([Char] -> t)) => t
Run Code Online (Sandbox Code Playgroud)

printf haskell variadic-functions polyvariadic

99
推荐指数
1
解决办法
1万
查看次数

如何创建polyvariadic haskell函数?

我需要一个函数,它接受任意数量的参数(所有相同的类型),对它们做一些事情然后给出一个结果.在我的具体情况下,参数列表是不切实际的.

当我查看haskell库时,我看到函数printf(来自模块Text.Printf)使用了类似的技巧.不幸的是,通过查看来源我无法理解这种魔力.

有人可以解释如何实现这一点,或至少一些网页/纸/任何我可以找到一个良好的描述吗?

动机:

我需要它的原因非常简单.对于学校(计算机科学课),我们需要编写一个能够"记录"数学表达式,将其表示为字符串的模块(通过为自己的数据类型编写Num/Real/etc的实例),并执行对它的各种操作.

此数据类型包含变量的特殊构造函数,可以由值或指定函数的任何值替换.其中一个目标是编写一个函数,它使用一些变量(类型对(Char,Rational))来表达这种表达式并计算表达式的结果.我们应该看看如何最好地表达函数的目标.(我的想法:该函数返回另一个函数,它接受与函数中定义的变量一样多的参数 - 似乎是不可能的).

haskell variadic-functions function-parameter polyvariadic

69
推荐指数
5
解决办法
1万
查看次数

Haskell"申请"?

可能重复:
为什么haskell中不允许这样的函数定义?

我是Haskell世界的新手,从Lisp迁移过来.我正在努力适应Haskell根本不同的世界观,而我发现的许多令人兴奋的事情之一就是类型系统.作为一个Lisper,我想我会尝试在Haskell中实现一个在Lisp世界中非常重要的函数:apply.对于那些不知道的人,apply接受一个函数和一个参数列表,并在这些参数上调用该函数.在Scheme中,(apply + '(1 2 3))与调用相同(+ 1 2 3),并返回6.

我的Haskell代码看起来像这样:

apply x [] = x
apply f (x:xs) = apply (f x) xs
Run Code Online (Sandbox Code Playgroud)

但哈斯克尔抱怨道:

ERROR line 2 - Type error in function binding
*** Term           : apply
*** Type           : (b -> a) -> [b] -> a
*** Does not match : a -> [b] -> a
*** Because        : unification would give infinite type
Run Code Online (Sandbox Code Playgroud)

而且我认为我理解为什么.Apply的类型需要根据列表的长度而有所不同.给出一个例如3个项目的列表,apply的类型需要是:(a -> a -> a -> b) …

lisp haskell types polyvariadic

20
推荐指数
1
解决办法
7706
查看次数

Haskell中的多变量函数

在阅读了关于在Haskell中编写多变量函数的这篇文章后,我试着写一些自己的函数.

起初我以为我会尝试概括它 - 所以我可以通过折叠参数给出一个返回可变参数函数的函数.

{-# OPTIONS -fglasgow-exts #-}
module Collapse where
class Collapse a r | r -> a where
  collapse :: (a -> a -> a) -> a -> r
instance Collapse a a where
  collapse _ = id
instance (Collapse a r) => Collapse a (a -> r) where
  collapse f a a' = collapse f (f a a')
Run Code Online (Sandbox Code Playgroud)

但是,编译器不喜欢这样:

Collapse.hs:5:9:
    Functional dependencies conflict between instance declarations:
      instance Collapse a a -- Defined at …
Run Code Online (Sandbox Code Playgroud)

polymorphism haskell polyvariadic

15
推荐指数
2
解决办法
1681
查看次数

如何在Haskell中定义一个任意的arity函数,其中包含一个0的arity?

我目前定义任意arity函数的方法如下,A是累加器,E是输入参数类型,R是结果类型.

combine :: A -> E -> A

class X r where
    foo :: A -> E -> r

instance X R where
    foo :: A -> E -> R


instance X r => X ( E -> r ) where
    foo :: A -> E -> E -> r
    foo ( a :: A ) ( x :: E ) =
        foo ( a `combine` e :: A )

doFoo = foo emptyA
Run Code Online (Sandbox Code Playgroud)

但是foo的最小arity是1.foo的最小值仍然是A - > E - > …

haskell polyvariadic

10
推荐指数
1
解决办法
578
查看次数

具有IO的Haskell Polyvariadic函数

是否有可能有一个函数接受外部函数调用,其中一些外部函数的参数是CString并返回一个接受String的函数?

这是我正在寻找的一个例子:

 foreign_func_1 :: (CDouble -> CString -> IO())
 foreign_func_2 :: (CDouble -> CDouble -> CString -> IO ())

 externalFunc1 :: (Double -> String -> IO())
 externalFunc1 = myFunc foreign_func_1

 externalFunc2 :: (Double -> Double -> String -> IO())
 externalFunc2 = myFunc foreign_func_2
Run Code Online (Sandbox Code Playgroud)

我想出了如何使用C数字类型执行此操作.但是,我无法找到一种可以允许字符串转换的方法.

这个问题似乎适合IO函数,因为转换为CStrings的所有内容(如newCString或withCString)都是IO.

以下是处理转换双精度的代码.

class CConvertable interiorArgs exteriorArgs where
   convertArgs :: (Ptr OtherIrrelevantType -> interiorArgs) -> exteriorArgs

instance CConvertable (IO ()) (Ptr OtherIrrelevantType -> IO ()) where
   convertArgs = doSomeOtherThingsThatArentCausingProblems
instance (Real b, Fractional a, CConvertable intArgs extArgs) …
Run Code Online (Sandbox Code Playgroud)

haskell ffi polyvariadic

9
推荐指数
2
解决办法
735
查看次数

在Haskell中,我如何获取m-ary谓词和n-ary谓词并构造一个(m + n)-ary谓词?

今天我玩了使用类型类来归纳地构造任何arity谓词的函数,将任何类型的任意组合作为输入,返回相同类型的其他谓词但应用了一些基本操作.例如

conjunction (>2) even
Run Code Online (Sandbox Code Playgroud)

会返回一个谓词,对于大于2的偶数,它的计算结果为真

conjunction (>=) (<=)
Run Code Online (Sandbox Code Playgroud)

会返回=

一切都很好,让这部分工作,但它提出了一个问题,如果我想将两个谓词的连接定义为一个谓词,为每个连接谓词的每个输入获取一个输入,该怎么办?例如:

:t conjunction (>) not
Run Code Online (Sandbox Code Playgroud)

将返回Ord a => a - > a - > Bool - > Bool.可以这样做吗?如果是这样,怎么样?

haskell typeclass polyvariadic

7
推荐指数
1
解决办法
258
查看次数

多变量广义和

这个答案演示了一个多变量函数,它总结了它的参数:

class SumRes r where 
    sumOf :: Integer -> r

instance SumRes Integer where
    sumOf = id

instance (Integral a, SumRes r) => SumRes (a -> r) where
    sumOf x = sumOf . (x +) . toInteger
Run Code Online (Sandbox Code Playgroud)

我为以下所有成员创建了此函数的通用版本Num:

class (Num n) => MySumType n r where
    mySum :: n -> r

instance (Num n) => MySumType n n where
    mySum x = x

instance (Num n, MySumType n r) => MySumType n (n->r) where
    mySum x = …
Run Code Online (Sandbox Code Playgroud)

haskell polyvariadic

6
推荐指数
1
解决办法
269
查看次数

多变量咖喱定义中的模糊类型变量

所以,我正在尝试实现这里描述的多变量ZipWithN .不幸的是,Paczesiowa的代码似乎是用ghc和HList的过时版本编译的,所以在试图理解它如何工作的过程中,我也将它移植到这两个版本的最新版本(ghc- 7.8.3和此时的HList-0.3.4.1).这很有趣.

无论如何,在中间函数的定义中,我遇到了谷歌没有帮助我修复一次的错误curryN'.在概念上,curryN'很简单:它采用类型级自然数N(或严格来说,该类型的值),以及f第一个参数是长度为HList的函数N,并返回一个N带有HList的-ary函数超出其第一个N参数,并将返回f应用于该HList.它是curry,但是多变量.

它使用三个辅助函数/类:

第一个是ResultType/ resultType,正如我在这里定义的那样. resultType将单个函数作为参数,并在将该函数应用于所需的参数之后返回该函数的类型.(严格地说,它再次返回该类型的未定义值).

例如:

ghci> :t resultType (++)
resultType (++) :: [a]
ghci> :t resultType negate
resultType negate :: (ResultType a result, Num a) => result
Run Code Online (Sandbox Code Playgroud)

(后一种情况,因为如果a恰好是类型的函数x -> y,则resultType必须返回y.因此它不适用于多态函数.)

后两个是和Eat/ eatMComp/ mcomp,一起定义(连同curryN')在一个文件中(连同破碎curryN')像这样 …

haskell function currying polyvariadic

6
推荐指数
0
解决办法
182
查看次数

在C#类型约束中指定"任何子类"而不是"一个特定子类"

如果我想编写一个方法,它采用可变数量的"TDerived",其中TDerived是类"Base"的任何子类,有没有办法做到这一点?

以下代码仅适用于单个特定的指定子类:

void doStuff<TDerived>(params TDerived[] args) where TDerived : Base
{
    //stuff
}
Run Code Online (Sandbox Code Playgroud)

即如果我有

class Super { }
class Sub0 : Super { }
class Sub1 : Super { }
Run Code Online (Sandbox Code Playgroud)

那我就做不到了

Sub0 s0 = new Sub0();
Sub1 s1 = new Sub1();
doStuff(s0, s1);
Run Code Online (Sandbox Code Playgroud)

因为我得到"最好的重载匹配......有一些无效的论点".

无论编译器如何处理类型约束和可变参数函数,这似乎(据我所知)完全类型安全.我知道我可以施放,但如果这是类型安全的,为什么不允许它?

编辑:

也许是一个更有说服力的例子:

void doStuff<TDerived>(params SomeReadOnlyCollection<TDerived>[] args) where TDerived : Base
{
    foreach(var list in args)
    {
        foreach(TDerived thing in list)
        {
            //stuff
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

c# polyvariadic

5
推荐指数
2
解决办法
719
查看次数