在Haskell中,是否有一种通用的方法可以判断一个函数的参数数量? [英] Is there a general way to tell the number of parameters of a function in Haskell?

查看:65
本文介绍了在Haskell中,是否有一种通用的方法可以判断一个函数的参数数量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我可以用以下代码告诉一个函数的参数数量

I can tell the number of parameters of a function with the following code

{-#Language MultiParamTypeClasses#-}
{-#Language FunctionalDependencies#-}
{-#Language UndecidableInstances#-}

data Zero
data Succ a

class Number a
instance Number Zero
instance (Number a) => Number (Succ a)

class NotFunction a
instance NotFunction Int
instance NotFunction Float
instance NotFunction (IO a)

class (Number n) => FunctionLevel f n | f -> n where
  functionLevel :: f -> n
instance FunctionLevel Int Zero where
  functionLevel = undefined
instance FunctionLevel Float Zero where
  functionLevel = undefined
instance FunctionLevel (IO a) Zero where
  functionLevel = undefined
instance FunctionLevel Double Zero where
  functionLevel = undefined
instance (FunctionLevel f' n) => FunctionLevel (a->f') (Succ n) where
  functionLevel = undefined

然后我们得到:

*Main> :t functionLevel (undefined::a->b->Int)
functionLevel (undefined::a->b->Int) :: Succ (Succ Zero)
*Main> :t functionLevel (undefined::a->b->Double)
functionLevel (undefined::a->b->Double) :: Succ (Succ Zero)
*Main> :t functionLevel (undefined::a->b->c->d->IO a)
functionLevel (undefined::a->b->c->d->IO a)
  :: Succ (Succ (Succ (Succ Zero)))
*Main> :t functionLevel (undefined::a->b->c->d->Int)
functionLevel (undefined::a->b->c->d->Int)
  :: Succ (Succ (Succ (Succ Zero)))

如您所见,functionLevel的执行与我们对带有某些特殊类型的结束"函数的预期一样.我的问题是:我们可以将其概括为一个任意函数的参数号吗?

As you can see, functionLevel performs just as we expected for functions "ended" with some special types. My question is: could we generalize this to tell parameter number of an arbitrary function?

推荐答案

只是一个想法;您可以使用以下代码来判断函数在值级别上的参数数量.

Just an idea; you can tell the number of parameters of a function at value level with the following code.

https://gist.github.com/nushio3/5867066

import Data.Typeable
import Test.Hspec

arityOf :: Typeable a => a -> Int
arityOf x = go $ typeOf x
  where
    go tr
      | isFun $ typeRepTyCon tr = 1 + go (last $ snd $ splitTyConApp tr)
      | otherwise               = 0

    funTyCon = typeRepTyCon $ typeOf ((1+):: Int -> Int)
    isFun = (funTyCon ==)

main :: IO ()
main = hspec spec

func :: (Int -> Int) -> Int -> Int
func = undefined

spec :: Spec
spec = describe "arityOf" $ do
  it "evaluates Integers correctly" $ arityOf (1::Int) `shouldBe` 0
  it "evaluates Strings correctly" $ arityOf "(1::Int)" `shouldBe` 0
  it "evaluates monads correctly" $ arityOf main `shouldBe` 0
  it "evaluates multiplications correctly" $ arityOf ((*) :: Int -> Int -> Int)
    `shouldBe` 2
  it "is not deceived by non-tail argument" $ arityOf func `shouldBe` 2

这篇关于在Haskell中,是否有一种通用的方法可以判断一个函数的参数数量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆