gpt4 book ai didi

function - 根据类型为泛型函数提供不同的函数体

转载 作者:行者123 更新时间:2023-12-04 17:26:26 26 4
gpt4 key购买 nike

假设我有一些通用功能

genericFunc :: a -> b
genericFunc x = doSomeHardWork

但是对于特定类型,有一种更有效的方法, genericFunc可以做到。
genericFunc :: ParticularType -> b
genericFunc x = doSomeEasyWork

将这两个函数体组合成同一个 genericFunc 的最佳方法是什么? , 这样当用于 ParticularType ,它将 doSomeEasyWork ,但是当用于其他类型时,它将 doSomeHardWork ?我特别排除了使用不同名称或不同模块的选项。

我相信这可以通过 typeclass 来完成,但我对使用语言 pragma 的解决方案更感兴趣。我有一个模糊的想法,这可以通过语言杂注来完成,但我不知道如何。如果您比较和对比这些方法和/或任何其他可能的方法,则可以加分。

最佳答案

这可以通过在类定义中定义通用方法并在实例中覆盖它来使用类型类来完成。将始终使用被覆盖的函数。

class ContainsInt c where
toList :: c -> [Int]

-- generic function
elem :: Int -> c -> Bool
elem n x = Prelude.elem n (toList x)

instance ContainsInt () where
toList _ = []

-- Override the generic function for type ()
elem _ _ = False

GHC 支持的另一种方法是使用重写规则。重写规则告诉 GHC 尽可能用另一个表达式替换一个表达式。如果替换是错误类型的,则不会执行,因此您可以使用它来替换专用版本的函数。重写规则由 {-# RULES #-} 给出语用。
class ContainsInt c where
toList :: c -> [Int]

elem :: ContainsInt c => Int -> c -> Bool
elem n x = Prelude.elem n (toList x)

-- Replace 'elem' by 'elemUnit' if it has the same type
{-# RULES "elem()" forall. elem = elemUnit #-}

elemUnit :: Int -> () -> Bool
elemUnit _ _ = False

重写规则由编译器自行决定执行,因此在任何给定情况下可能会或可能不会调用专用函数。例如,重写可能取决于编译器是否决定内联函数:
foo :: ContainsInt c -> Int -> [c] -> [Bool]
-- Must use the generic function
foo n cs = map (elem n) cs

useFoo :: Int -> [()] -> [Bool]
-- If 'foo' is inlined and 'elem' is not inlined, then this function will contain a rewritable call to 'elem'.
-- Otherwise rewriting cannot happen.
useFoo n cs = foo n cs

关于function - 根据类型为泛型函数提供不同的函数体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8467391/

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