如何在Haskell的内部函数中重用父函数的类型约束和参数



我正在尝试重构下面的教程练习答案,但遇到了麻烦。

首先,我想在内部函数中使用在外部函数中声明的arr参数。我认为它会在作用域中,就像在Javascript中一样。

所以这个:

maxIndex :: (Ix sourceIndexType, Ord sourceElementType) => Array sourceIndexType sourceElementType -> sourceIndexType
maxIndex arr = findLargestIndexOfElement arr (findLargestElement arr)
where
findLargestElement :: (Ix sourceIndexType, Ord sourceElementType) => Array sourceIndexType sourceElementType -> sourceElementType
findLargestElement arr = maximum $ elems arr
findLargestIndexOfElement :: (Ix sourceIndexType, Ord sourceElementType) => Array sourceIndexType sourceElementType -> sourceElementType -> sourceIndexType
findLargestIndexOfElement arr element = fst $ foldr1 ((itemk,itemv) (acck, accv) -> if element==itemv then (itemk,itemv) else (acck,accv)) (assocs arr)

成为

maxIndex :: (Ix sourceIndexType, Ord sourceElementType) => Array sourceIndexType sourceElementType -> sourceIndexType
maxIndex arr = findLargestIndexOfElement arr findLargestElement 
where
findLargestElement :: sourceElementType
findLargestElement = maximum $ elems arr
findLargestIndexOfElement :: sourceElementType -> sourceIndexType
findLargestIndexOfElement element = fst $ foldr1 ((itemk,itemv) (acck, accv) -> if element==itemv then (itemk,itemv) else (acck,accv)) (assocs arr)

但是Haskell似乎无法从内部函数访问任何更高级别的定义。我的理解正确吗?哈斯克尔不能这样做吗?

我想做的下一个简化是重用参数的类型约束。因此,原始代码将变为:

maxIndex :: (Ix sourceIndexType, Ord sourceElementType) => Array sourceIndexType sourceElementType -> sourceIndexType
maxIndex arr = findLargestIndexOfElement arr (findLargestElement arr)
where
findLargestElement :: Array sourceIndexType sourceElementType -> sourceElementType
findLargestElement arr = maximum $ elems arr
findLargestIndexOfElement :: Array sourceIndexType sourceElementType -> sourceElementType -> sourceIndexType
findLargestIndexOfElement arr element = fst $ foldr1 ((itemk,itemv) (acck, accv) -> if element==itemv then (itemk,itemv) else (acck,accv)) (assocs arr)

但是这个变化也使Haskell出错。它完全忽略了任何函数中的sourceIndexType是同一类型。我不妨把它们都称为paramType1paramType2blue58。我如何让Haskell明白我对每种类型都使用相同的类型??

谢谢。

默认情况下,即使启用了-XScopedTypeVariables,Haskell类型变量也只有一个类型签名作为其作用域。要使作为签名的整个函数成为作用域,需要显式量化类型变量。
{-# LANGUAGE ScopedTypeVariables, UnicodeSyntax #-}
maxIndex :: ∀ sIt sEt. (Ix sIt, Ord sEt) => Array sIt sEt -> sIt
maxIndex arr = findLargestIndexOfElement arr largestElement 
where
largestElement :: sEt
largestElement = maximum $ elems arr
findLargestIndexOfElement :: sEt -> sIt
findLargestIndexOfElement element
= fst $ foldr1 ((itemk,itemv) (acck, accv)
-> if element==itemv then (itemk,itemv)
else (acck,accv))
(assocs arr)

最新更新