具有多种参数类型的多态输入函数
Polymorphic input function with multiple argument types
出于纯粹的好奇心,我想知道在 Haskell 中可能会出现类似以下的情况:
函数 foo
将另一个函数作为参数,该函数在 foo
的主体中多次调用,并在此过程中更改参数的类型。
以下代码无法编译,因为 fn
的参数类型一旦被调用就被固定下来,但希望它能说明我在胡说什么。
main = putStrLn (foo id)
foo :: (* -> *) -> [Char] -- maybe I'm also getting the whole *-thing wrong
foo fn =
let
val1 = fn "hey"
val2 = fn 42
in
show (val1, val2)
我想知道它是否可以实现,如果没有像类型类这样的助手,你是否可以做到。
您要找的是 extension called RankNTypes
。使用它,您可以将函数的类型写为:
{-# LANGUAGE RankNTypes #-}
foo :: (forall a. a -> a) -> [Char]
在这种情况下,您唯一可以提供的函数是 id
,但您也可以使用类型 类 来允许稍微更有趣的多态函数作为参数。考虑这个版本的函数:
bar:: (forall a. Show a => a -> String) -> String
bar fn =
let
val1 = fn "hey"
val2 = fn 42
in
val1 <> val2
*
不是允许使用任何类型的通配符。所以,你的用法是错误的。
要键入您的函数,我们需要指定 fn
的类型。那必须是一个多态函数 returning 一些可以 Show
ed 的值。
一个可能的解决方案是:
{-# LANGUAGE ScopedTypeVariables, RankNTypes #-}
foo :: forall b. Show b => (forall a. a -> b) -> [Char]
foo fn = let
val1 = fn "hey"
val2 = fn 42
in show (val1, val2)
这要求 fn
接受任何类型 a
和 return 固定类型 b
class Show
。
正如所写,这不是很有用,因为 fn
无法使用它的参数,因为它是泛型类型 a
.
也许更有用的变体是 a
属于某种类型 class c
,这样至少可以使用 fn
的参数至 c
.
foo :: forall b c. (Show b, c String, c Int)
=> (forall a. c a => a -> b) -> [Char]
foo fn = let
val1 = fn "hey"
val2 = fn (42 :: Int)
in show (val1, val2)
出于纯粹的好奇心,我想知道在 Haskell 中可能会出现类似以下的情况:
函数 foo
将另一个函数作为参数,该函数在 foo
的主体中多次调用,并在此过程中更改参数的类型。
以下代码无法编译,因为 fn
的参数类型一旦被调用就被固定下来,但希望它能说明我在胡说什么。
main = putStrLn (foo id)
foo :: (* -> *) -> [Char] -- maybe I'm also getting the whole *-thing wrong
foo fn =
let
val1 = fn "hey"
val2 = fn 42
in
show (val1, val2)
我想知道它是否可以实现,如果没有像类型类这样的助手,你是否可以做到。
您要找的是 extension called RankNTypes
。使用它,您可以将函数的类型写为:
{-# LANGUAGE RankNTypes #-}
foo :: (forall a. a -> a) -> [Char]
在这种情况下,您唯一可以提供的函数是 id
,但您也可以使用类型 类 来允许稍微更有趣的多态函数作为参数。考虑这个版本的函数:
bar:: (forall a. Show a => a -> String) -> String
bar fn =
let
val1 = fn "hey"
val2 = fn 42
in
val1 <> val2
*
不是允许使用任何类型的通配符。所以,你的用法是错误的。
要键入您的函数,我们需要指定 fn
的类型。那必须是一个多态函数 returning 一些可以 Show
ed 的值。
一个可能的解决方案是:
{-# LANGUAGE ScopedTypeVariables, RankNTypes #-}
foo :: forall b. Show b => (forall a. a -> b) -> [Char]
foo fn = let
val1 = fn "hey"
val2 = fn 42
in show (val1, val2)
这要求 fn
接受任何类型 a
和 return 固定类型 b
class Show
。
正如所写,这不是很有用,因为 fn
无法使用它的参数,因为它是泛型类型 a
.
也许更有用的变体是 a
属于某种类型 class c
,这样至少可以使用 fn
的参数至 c
.
foo :: forall b c. (Show b, c String, c Int)
=> (forall a. c a => a -> b) -> [Char]
foo fn = let
val1 = fn "hey"
val2 = fn (42 :: Int)
in show (val1, val2)