繁体   English   中英

如何在没有泛型类型参数的情况下定义泛型函数?

[英]How to define generic function without argument of generic type?

我现在正在阅读“Haskell Book”的monoid部分,作者使用QuickCheck检查幺半群定律。 在我自己写完一些东西后,我有这个代码:

module Main where

import Data.Monoid
import Test.QuickCheck

monoidAssoc :: (Eq m, Monoid m) => m -> m -> m -> Bool
monoidAssoc a b c = ((a <> b) <> c) == (a <> (b <> c))

monoidLeftId :: (Eq m, Monoid m) => m -> Bool
monoidLeftId a = (mempty <> a) == a

monoidRightId :: (Eq m, Monoid m) => m -> Bool
monoidRightId a = (a <> mempty) == a

type AssocCheck a = a -> a -> a -> Bool
type IdCheck a = a -> Bool

main :: IO ()
main = do
  quickCheck (monoidAssoc   :: AssocCheck (Maybe String))
  quickCheck (monoidLeftId  :: IdCheck (Maybe String))
  quickCheck (monoidRightId :: IdCheck (Maybe String))

  quickCheck (monoidAssoc   :: AssocCheck [String])
  quickCheck (monoidLeftId  :: IdCheck [String])
  quickCheck (monoidRightId :: IdCheck [String])

正如你所看到的, main函数有两个几乎相同的块,我想减少到这样的东西:

checkMonoid :: (Eq m, Monoid m) => m -> IO ()
checkMonoid = do
  quickCheck (monoidAssoc   :: AssocCheck m)
  quickCheck (monoidLeftId  :: IdCheck m)
  quickCheck (monoidRightId :: IdCheck m)


main :: IO ()
main = do
  checkMonoid :: Maybe String -> IO ()
  checkMonoid :: [String] -> IO ()

但这显然不会起作用。 我想要的是以某种方式将类型传递给checkMonoid函数,因此quickCheck函数将知道必须生成哪些arbitrary数据。

这正是TypeApplication允许您执行的操作 - 您可以显式传递m的类型。 那么你还需要ScopedTypeVariables ,以确保所有的m ,你在s checkMonoid是相同的,并且AllowAmbiguousTypes让GHC知道你是罚款的事实, checkMonoid将是暧昧不用类型的应用程序。

{-# LANGUAGE TypeApplications, AllowAmbiguousTypes, ScopedTypeVariables #-}

-- ...

checkMonoid :: forall m. (Eq m, Monoid m, Show m, Arbitrary m) => IO ()
checkMonoid = do
  quickCheck (monoidAssoc   :: AssocCheck m)
  quickCheck (monoidLeftId  :: IdCheck m)
  quickCheck (monoidRightId :: IdCheck m)


main :: IO ()
main = do
  checkMonoid @(Maybe String)
  checkMonoid @[String]

背后的主要TypeApplications是引擎盖下Haskell是转变态函数到函数,也采取类型作为参数( 参见更多在这里 ) -和常GHC负责搞清楚哪种类型的参数,以填补在TypeApplications@SomeType说“让前面函数调用的第一个类型参数为SomeType “。

通过拥有forall m. 我确保GHC会做到以上几点。 然后,当我调用checkMonoid ,我明确地传递了m的类型。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM